C++在两个不同的向量中的相同对象

C++ same object in two different vectors

本文关键字:向量 对象 两个 C++      更新时间:2023-10-16

我正在处理一个C++项目,我想知道是否可以将同一个对象存储在两个不同的向量中。我知道如何在C中用指针处理它,所以你对两个表都引用了同一个对象,但我在C++中有点困惑。

如果我创建了一个对象,并将其存储在向量a和向量b中。C++是否复制该对象,或者它在两个向量上都相同,如果我修改了一个,另一个也被修改了?在第二种情况下,存储两次(针对可访问性问题)是否需要更多的位置,或者这不是一个好的处理方法?

谢谢。

Cppreference是检查这类问题的好地方。让我引用链接的相关部分:

void push_back(const T&value);

void push_back(T&&value);

将给定的元素值追加到容器的末尾。

1) 新元素被初始化为值的副本。

2) 值移动到新元素中。

所以,是的,将同一个元素在两个向量中存储两次会导致它被复制两次。如果不想浪费内存,您应该使用std::vector<T*>。和往常一样,您还应该考虑智能指针(std::shared_ptr/std::weak_ptr),而不是裸指针。

它与C非常相似。

如果您拥有的是vector<object>,那么您将使用不同的对象。

另一方面,vector<object*>确保您只存储指向对象的指针,然后让多个向量包含同一个或多个对象不是问题。

在C++中使用指针时,您还可以考虑使用std::shared_ptrstd::weak_ptr来简化内存管理。

当您将对象插入std::vector时,会生成它的副本:

Foo a;
std::vector<Foo> vec1;
std::vector<Foo> vec2;
vec1.push_back(a); //copy made
vec2.push_back(b); //copy made

如果您不想要副本,可以使用指针或std::reference_wrapper(不能使用引用,因为它们不满足容器值类型的限制):

Foo a;
std::vector<Foo*> vec1;
std::vector<std::reference_wrapper<Foo>> vec2;
vec1.push_back(&a); //no copy
vec2.push_back(std::ref(b)); //no copy

当然,现在不需要确保a的寿命不短于向量的寿命,否则您将处于未定义行为的快速通道上。

您也可以使用std::shared_ptr,它将确保您的对象在没有更多引用时被销毁:

std::shared_ptr<Foo> a = std::make_shared<Foo>();
std::vector<std::shared_ptr<Foo>> vec1;
std::vector<std::shared_ptr<Foo>> vec2;
vec1.push_back(a); //reference count incremented
vec2.push_back(a); //reference count incremented

我为您举了一个简单的例子:

class SomeObject { public: int a; };
int main()
{
    SomeObject some_object;
    some_object.a = 1;
    //Copies are made
    std::vector<SomeObject> foo;
    foo.push_back(some_object);
    std::vector<SomeObject> bar;
    bar.push_back(some_object);
    foo.at(0).a = 2;
    bar.at(0).a = 3;
    std::cout << foo.at(0).a << ' ' << bar.at(0).a;
    //Refers to the same object
    std::vector<SomeObject*> baz;
    baz.push_back(&some_object);
    std::vector<SomeObject*> foobar;
    foobar.push_back(&some_object);
    baz.at(0)->a = 4;
    foobar.at(0)->a = 5;
    std::cout << ' ' << baz.at(0)->a << ' ' << foobar.at(0)->a;
    return 0;
}

输出:

2 3 5 5