为什么应使用指针而非对象本身?

为什么应使用指针而非对象本身?

技术背景

在C++编程中,对象的创建和使用有两种常见方式:直接创建对象和使用指针创建对象。这两种方式各有优缺点,了解何时使用指针而非对象本身,对于编写高效、安全的C++代码至关重要。

实现步骤

动态分配与指针使用场景

  1. 动态分配(使用 new
    • 对象生命周期超出当前作用域:当需要对象在创建它的作用域结束后仍然存在时,使用动态分配。例如,在函数中创建一个对象,该对象需要在函数返回后继续使用。
    • 大量内存分配:栈空间有限,当需要分配大量内存时,使用动态分配可以避免栈溢出。
  2. 指针的使用场景
    • 引用语义:当需要函数访问特定对象而不是对象的副本时,使用指针。不过,在大多数情况下,引用类型更受青睐。
    • 多态性:通过指针或引用可以实现多态调用,即根据对象的动态类型调用函数。
    • 表示对象可选:允许传递 nullptr 来表示对象不存在。但建议优先使用默认参数、函数重载或 std::optional
    • 解耦编译单元:使用指针只需要前向声明,从而解耦编译过程,提高编译时间。
    • 与C库或C风格库交互:在与这些库交互时,必须使用原始指针。

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <iostream>
#include <memory>
#include <vector>

// 基类
class Base {
public:
virtual void print() {
std::cout << "Base" << std::endl;
}
};

// 派生类
class Derived : public Base {
public:
void print() override {
std::cout << "Derived" << std::endl;
}
};

int main() {
// 动态分配对象
Base* basePtr = new Derived();
basePtr->print(); // 多态调用
delete basePtr;

// 使用智能指针
std::unique_ptr<Base> smartPtr = std::make_unique<Derived>();
smartPtr->print();

// 多态数组
std::vector<Base*> polyVector;
polyVector.push_back(new Derived());
for (auto ptr : polyVector) {
ptr->print();
delete ptr;
}

return 0;
}

核心代码

动态分配对象

1
2
3
Object* myObject = new Object();
// 使用对象
delete myObject; // 手动释放内存

使用智能指针

1
2
3
#include <memory>
std::unique_ptr<Object> smartObject = std::make_unique<Object>();
// 使用对象,无需手动释放内存

多态调用

1
2
3
4
5
6
7
8
9
10
11
12
13
class Base {
public:
virtual void func() {}
};

class Derived : public Base {
public:
void func() override {}
};

Base* basePtr = new Derived();
basePtr->func(); // 多态调用
delete basePtr;

最佳实践

  1. 优先使用自动存储期对象:在大多数情况下,优先创建具有自动存储期的对象,因为它们会在作用域结束时自动销毁,避免手动内存管理。
  2. 使用智能指针:当需要动态分配内存时,使用智能指针(如 std::unique_ptrstd::shared_ptr)来管理内存,避免内存泄漏。
  3. 优先使用引用:在需要引用语义时,优先使用引用而不是指针,因为引用更安全。
  4. 避免不必要的指针使用:除非有明确的需求,否则不要使用指针。许多情况下,有更安全和合适的替代方案。

常见问题

  1. 内存泄漏:手动使用 newdelete 时,容易忘记释放内存,导致内存泄漏。解决方法是使用智能指针。
  2. 空指针异常:使用指针时,可能会遇到空指针,导致程序崩溃。在使用指针之前,应该检查指针是否为空。
  3. 对象切片:在多态调用中,如果不使用指针或引用,可能会发生对象切片,导致意外的结果。
  4. 指针算术错误:指针算术操作容易出错,应该谨慎使用。

为什么应使用指针而非对象本身?
https://119291.xyz/posts/why-should-use-pointer-rather-than-object/
作者
ww
发布于
2025年5月26日
许可协议