c++中共享vector的类的几个实例(但不是全部)



我想有一个类C,这样C的实例将std::vector<int>作为私有成员。现在C的许多实例(但不是全部)将共享该向量,并且为每个实例保留一个副本是我想要避免的。

例如,如果这个向量是一个整数,我可以为C创建一个模板类,并像这样:

template <int N>
class C {
// something
};

如果我希望所有的实例都共享这个向量,那么我可以声明static变量为

class C {
static std::vector<int> _vec;

我要找的是中间的东西。例如,我可以保留shared_ptr作为私有非静态成员,如

class C {
std::shared_ptr<std::vector<int>> _vec;
}

这将照顾到对象的生命周期,有一些维护共享所有权的开销和每个实例的额外指针。我可以保留一个引用,让实例的创建者来处理生命周期,但避免shared_ptr的开销。是否有更好的方法来解决这个设计问题?

…使得C的实例保存std::vector作为私有成员。现在,C的许多实例(但不是全部)将共享这个向量

这是自相矛盾的。你不可能安全地持有一个实例并共享它。

这是指针的经典用例;更具体地说,是共享指针的经典用例,正如您已经注意到的。

我可以保留一个引用,让实例的创建者来处理生命周期,

/me发出破坏后访问报警你很快就会发现这是行不通的。生命周期并不像你想象的那样,而是在拥有对象的生命周期结束时结束。所以,这个断裂了。(此外,你会发现,在底层,分发引用编译成与分发原始指针相同的代码-它只是更安全,并且在语言中自动解除引用;你实际上并没有间接地节省内存。包含引用的类仍然需要知道它们正在处理的对象的地址,如果你问你的CPU,这与拥有指针是一样的。

它会崩溃,除非分发引用的东西保留了它分发的引用的数量,减去它分发的属于被解构的C实例的引用的数量,然后在该数字达到0时解构向量。大胆猜猜shared_ptr是做什么的!正是这个引用计数

然而,访问逻辑通常更容易;例如,

我有一个矢量C,std::vector<C> lexicon,所有持有的C._vec需要在完整的lexicon超出范围时被删除,所以我手动处理

实际上不需要引用计数,因此开销较低。你确实可以通过分发引用来解决这个问题——但在这种情况下,我实际上更喜欢分发原始指针:它们并不意味着所有权,而且当你按值传递指针时,你不会意外地复制std::vector<int>

如果你的终身跟踪不像这个例子那么容易:

在引用中没有神奇的用法跟踪;你需要一些东西来跟踪是否有东西仍然持有你的个人vector的一些句柄。跟踪就是"管理费用"shared_ptr带来。没办法。

私有shared_ptr因此是正确的方法:

class C {
private:
std::shared_ptr<std::vector<int>> _vec;
}

您的static方法在这里没有任何用处—只有当所有和实际上所有实例共享从开始到结束都应该存在的相同向量时,它才有意义,即使这样,它也是一种解决方案,可能会导致静态初始化顺序惨败的形式的额外头痛。我建议在任何情况下都不要那样做。

(另外,static成员也只是归结为查找相同地址的代码-因此,性能方面,与指针相同。再说一遍,这里什么也没赢。

最新更新