指向器的C++容器/对现有对象的引用

C++ Container of Pointers/References to Existing Objects

本文关键字:对象 引用 容器 C++      更新时间:2024-09-23

我有一个现有的容器,里面装满了自动分配的结构对象,比如:

std::vector<Object> objectList {obj1, obj2, obj3};

我正在尝试创建一个新的容器useObjectList,它由指向那些现有对象的指针/引用组成,这样我就可以访问和修改任一列表中的对象成员值。

我试图通过创建一个共享指针的容器来实现这一点

std::vector<std::shared_ptr<Object>> useObjectList {std::make_shared<Object>(objectList[1])};

但它根本没有成功(鉴于我的知识有限,我假设std::make_shared完全构建和/或分配一个新对象?(。

如果能得到任何建议,我将不胜感激。

使用;"指向器的C++容器/对现有对象的引用";,或者其他任何东西,你应该理解所有权的概念。总结:所有权是清理的责任。您应该考虑哪个实体应该删除您的对象。通常,每当你更改代码或添加功能时,你都应该重新思考这一点

std::vector<Object> objectList {obj1, obj2, obj3};-这里,objectList包含对象obj1obj2obj3的副本,并负责删除它们(即拥有它们(。无论哪个实体包含原始obj1obj2obj3都保留这些实体的所有权(即将删除它们(。

更广泛的背景:

void do_stuff()
{
Object obj1;
Object obj2;
Object obj3;
std::vector<Object> objectList {obj1, obj2, obj3};
}

这里,函数do_stuff的作用域(或"堆栈帧"(拥有三个对象:当控制超出作用域时,它们将被删除。这是一种非对象拥有对象的情况。

std::vector<Object*> objectList {&obj1, &obj2, &obj3};-这里,objectList包含指向对象obj1obj2obj3的指针。物体本身的所有权没有改变——无论拥有什么,都会继续拥有它们。一些评论提到";总是建议避免使用原始指针"总是";这是无稽之谈,但这是一个很好的例子来说明这一建议。

更广泛的背景:

std::vector<Object*> someObjectList;
void do_stuff()
{
Object obj1;
Object obj2;
Object obj3;
std::vector<Object*> objectList {&obj1, &obj2, &obj3};
someObjectList = objectList;
}

这里,函数do_stuff的堆栈框架拥有这三个对象。如果你有指向这些对象的指针;发送";它们被发送到某个其他实体(someObjectList(,该实体即使在对象被清理之后也会存储指针。这就是为什么人们"建议避免使用原始指针";;但这里真正的问题更为根本——;现有对象的指针/引用的容器";。这是人们应该建议不要做的事情。

如果你真的想引用现有的对象,你应该确保你的所有权模式支持这一点。你可以通过以下任何一种方式做到这一点:

  1. 使用拥有对象的实体;确保指向对象的指针的所有列表在"删除"之前被删除;所有人";已删除。通常,应用程序的语义无论如何都要求这样做。

  2. 使用共享所有权。为此,您应该在对象的创建点应用共享所有权。

    std::shared_ptr<Object> obj1 = std::make_shared(whatever1);
    std::shared_ptr<Object> obj2 = std::make_shared(whatever2);
    std::shared_ptr<Object> obj3 = std::make_shared(whatever3);
    std::vector<std::shared_ptr<Object>> objectList(obj1, obj2, obj3);
    

    你应该考虑这样一种情况:;链接";指向对象的是指针列表。这在你的申请中有意义吗?如果是,请使用共享所有权。如果没有,这不是一个好主意,因为它隐藏了错误。

您可以使用reference_wrapper:

list<int> l {1, 2, 3, 4, 5};
vector<reference_wrapper<int>> v (l.begin(), l.end());
// you can't use subscription in list
// but as you are seeing elements by vector containing their references
// so operator[] works here.
cout << v[3] << 'n'; // outputs 4
for (auto& num : l) {
num *= 2; // original list elements are doubled
}
cout << v[2] << 'n'; // outputs 6