智能指针 vs 成员变量的值

8

我有一个类A,其中包含类型为M和N的成员变量。这些对象的生命周期应该受到A生命周期的限制。

我在考虑

class A {
    M member1;
    N member2;
}

对比。

class A {
    std::unique_ptr<M> member1;
    std::unique_ptr<N> member2;
}

我不确定哪种更好,因为它们都能实现我想要的功能。成员的生命周期绑定到对象上,我不需要手动管理内存。每种设置的优缺点是什么?


5
如果没有必要使用指针,为什么还要使用指针?在析构函数中,所有成员都会被“销毁”。 - NathanOliver
你唯一可能想要将 MN 创建为指针的情况是它们非常大,而在堆栈上创建它们可能会导致堆栈空间不足。 - Steve Lorimer
2
只有在必要且确实需要的情况下才使用动态内存分配。例如,如果您的成员对象非常庞大并可能会破坏堆栈,请使用动态分配。否则,请勿无谓地引入动态分配/间接引用的开销。 - underscore_d
请注意,后者默认情况下不可复制,而前者可以。 - Jarod42
3个回答

6

如果满足以下条件,请使用std::unique_ptr:

  1. M和N是多态层次结构的基类
  2. member1和member2是可选成员,可以为nullptr
  3. M和N太大,无法在程序堆栈上分配

这些就是所有的经验法则和发生情况吗? - πάντα ῥεῖ

4

没错,两种方法都是正确的,但是...

一般来说,与保持对象为简单成员相比,动态分配对象会有额外的成本。您必须支付从自由存储分配它们的内存的额外开销,而不是仅使用A所分配的内存。每当需要访问它们时,您也将拥有间接引用。

如果这样做有所收益,您仍然可能希望选择智能指针路线。例如:

  1. 您可能希望在A对象的生命周期内更改member1或member2的值。如果M和N对象很大,智能指针方法可以使此操作变得廉价。
  2. 您可能想利用多态性。如果M或N是基类,则基于指针的实现将具有使用M或N的子类的灵活性。
  3. 基于指针的实现可以使您延迟分配member1或member2直到后来更合适的时间。

2
这取决于类型N和M的大小以及您计划如何使用“ A类”。 如果类型N和M很小,即一个机器字,那么创建和维护指针的额外开销是浪费空间和时间。
如果类型N和M非常大,并且您计划在堆栈上声明“ class A”的对象,则最好使用指针。 在这种情况下,类型N和M的大型对象将分配在堆区域中(并且很可能会防止您调试非常棘手的堆栈溢出问题)。
另一方面,如果您计划动态分配“ class A”的对象,则具有成员变量就足够了,因为在这种情况下,所有内容都将在堆区域中分配,而且还可以节省开销。
希望这很清楚。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接