5

对于这种情况:

    class A
    {
        //implementation
    };

    class B
    {
     public:
         B();
        ~B();
     private:
         std::vector<std::shared_ptr<A>> _innerArray;
    };

我应该怎么做B()才能创建一个具有有效状态的对象?我是否需要为A数组中的每个对象手动调用默认构造函数?我需要做一些特别的事情~B()吗?如果 B 类是糟糕设计的例子,请随意说出如何使它变得更好。谢谢。

编辑 所以,这是我在这里真正需要的方案。

在此处输入图像描述

因此,仅存储在 A 数组和所有其他对象中的实际值用于存储连接。最简单的示例 - A = 点,B = 通过选定点的线(或曲线),C = 由线描述的平面。希望它使问题更准确。

4

5 回答 5

5

要创建B处于有效状态的对象,您无需再做任何事情。您甚至不必为B. std::vector<std::shared_ptr<A>>那是 的成员B将在B的构造函数中默认初始化,这意味着它在容器中还没有任何元素。它也将在~B感谢std::vectorstd::shared_ptr析构函数中正确删除。

另一方面,例如,如果您想以某种方式对其进行初始化(即 3 个值),则可以在 a的构造函数初始化列表中使用std::vector'构造函数。例如:std::initializer_listB

class B
{
 public:
     B(): _innerArray{ std::make_shared<A>(),
                       std::make_shared<A>(),
                       std::make_shared<A>() } {}
    ~B() {}
 private:
     std::vector<std::shared_ptr<A>> _innerArray;
};

请记住,std::make_shared使用完美转发,因此您将A的构造函数参数作为函数参数而不是类对象本身传递。

回答您对设计的担忧,我想鼓励您在决定共享向量之前先考虑成员的专有所有权。

class B
{
 public:
     B();
    ~B();
 private:
     std::vector<std::unique_ptr<A>> _innerArray;
};

上述实施在许多方面更为有效。首先,它使您的设计更清楚谁负责As 的生命周期。Nextstd::unique_ptr更快,因为它不需要线程安全的引用计数。最后但并非最不重要的一点是,它不会花费任何额外的内存(与常规 C 指针相比),而std::shared_ptr可能需要数十字节(24-48)来存储共享状态数据,这在您对小型类进行操作时非常无效。这就是为什么我总是将std::unique_ptr智能指针用作我的首选,并且我只std::shared_ptr在真正需要它时才回退到它。

编辑:

回答您的编辑我将创建 3 个类容器A, B, C. 根据您是否需要它们是多态的事实,我会存储这样的值(非多态类型):

std::deque<A> as;
std::deque<B> bs;
std::deque<C> cs;

或(多态类型):

std::vector<std::unique_ptr<A>> as;
std::vector<std::unique_ptr<B>> bs;
std::vector<std::unique_ptr<C>> cs;

按此顺序(as必须比 寿命更长,bs并且bs必须比 寿命更长cs)。然后我将只使用std::vector<A*>内部B类和std::vector<B*>内部C类,而不使用任何智能指针。

我希望这会有所帮助。

编辑:

更改std::vectorstd::deque在第一种情况下允许容器元素的引用/指针在具有push_back(). 然而,它们将无法在擦除元素、排序或其他内容时存活下来。

于 2012-11-07T11:41:21.637 回答
2

如果你这样做,向量的大小为零元素,即内容被简单地正确初始化。如果向量是正大小(例如在调用resize向量之后),每个元素都会被正确初始化。由于元素是shared_ptrs,因此将调用的默认构造函数shared_ptr,这意味着您最终将得到一个空指针向量。

如果要从另一个容器复制内容,请使用向量构造函数的迭代器版本:

B (SomeContainerTypeContainingSharedPointers container)
: _innerArray (container.begin (), container.end () ) {
}

如果您不想从容器中初始化向量,而是从其他地方(例如动态创建对象)- 自己编写一个输入迭代器类型(即一种“工厂迭代器”)。

于 2012-11-07T11:21:09.823 回答
1

该向量是空的,因此您不必在默认构造函数中执行任何特殊操作。你也不需要做任何事情B()。当调用向量的析构函数时,引用计数shared_ptrs将自动减少。

于 2012-11-07T11:22:07.370 回答
1

Bt 默认std::shared_ptr<A>将用NULL. 要创建智能指针,请使用std::make_shared

_innerArray.push_back(std::make_shared<A>(/*constructor params here*/));

但是在您的示例中,向量是空的。

于 2012-11-07T11:22:18.230 回答
0

默认构造函数已经完成了所需的一切。你甚至可以B()不带任何损失地离开。

于 2012-11-07T11:23:38.883 回答