gpt4 book ai didi

c++ - 仅使用标准库创建 "Vector of References"的标准实践

转载 作者:行者123 更新时间:2023-11-28 06:07:32 26 4
gpt4 key购买 nike

我想创建一个对象,把对象放到一个vector中,并且仍然能够通过仅访问 vector 来修改同一对象.但是,我知道当一个对象是 push_back()vector , 该对象实际上被复制到 vector 中.因此,访问 vector 中的对象只会访问一个相似但不同的对象。

我是 C 语言的初学者,所以我知道我可以创建一个指向对象的指针,并制作一个指针 vector 。例如vector<Object *> .但是,好像 pointersdiscouraged在 C++ 中,和 references are preferred .然而,I cannot make a vector of references .

我只想使用标准库,所以 boost对我来说是禁区。

我听说过智能指针。但是,看起来好像有多种类型的智能指针。为此目的会不会太过分了?如果智能指针确实是答案,那么我该如何确定使用哪一个?

所以我的问题是:创建对象引用/指针 vector 的标准做法是什么?

换句话说,希望下面的(伪)代码能够工作。

#include <iostream>
#include <cstdlib>
#include <vector>

using namespace std;

class Object
{
public:
int field;
};

vector<Object> addToVector(Object &o)
{
vector<Object> v;
v.push_back(o);
v[0].field = 3; // I want this to set o.field to 3.

return v;
}

int main()
{
Object one;
one.field = 1;
cout << one.field << endl; // 1 as expected

Object &refone = one;
refone.field = 2;
cout << one.field << endl; // 2 as expected

vector<Object> v = addToVector(one);

cout << v[0].field << endl; // 3 as expected

cout << one.field << endl; // I want to get 3 here as well, as opposed to 2.


return 0;
}

最佳答案

I would like to create an object, put the object into a vector, and still be able to modify the same object by accessing only the vector. However, I understand that when an object is push_back() to a vector, the object is actually copied into the vector. As a result, accessing the object in the vector will merely access a similar, but different object.

我几乎可以肯定这不是您想要或“应该”想要的。请原谅我直接打开我的答案,但除非你有充分的理由这样做,否则你可能不想这样做。

为此 - 一个带有引用的 vector - 要工作,您必须保证在您持有对它们的引用时被引用的对象不会被移动或破坏。如果您将它们放在 vector 中,请确保 vector 未调整大小。如果您像示例中那样将它们放在堆栈上,那么不要让引用 vector 或其拷贝离开该堆栈帧。如果您想将它们存储在某个容器中,请使用 std::list(它是迭代器 - 基本上是指针 - 在插入或删除元素时不会失效)。

您已经注意到您不能拥有“真实”引用的 vector 。因此,原因是引用不可分配。考虑以下代码:

int a = 42;
int b = 21;
int & x = a; // initialisation only way to bind to something
int & y = b;
x = y;
b = 0;

在那之后,您从x 获得的值将是21,因为赋值并没有改变引用(绑定(bind)到b)而是改变被引用的对象, 一个。但是一个std::vector explicitly requires这个。

您现在可以着手编写一个围绕指针的包装器,例如...

template<typename T>
struct my_ref {
T * target;
// don't let one construct a my_ref without valid object to reference to
my_ref(T & t) : target(&t) {}
// implicit conversion into an real reference
operator T &(void) {
return *target;
}
// default assignment works as expected with pointers
my_ref & operator=(my_ref const &) = default;
// a moved from reference doesn't make sense, it would be invalid
my_ref & operator=(my_ref &&) = delete;
my_ref(my_ref &&) = delete;
// ...
};

...但是自 std::reference_wrapper 以来这是毫无意义的已经准确地提供了:

int main (int, char**) {
int object = 21; // half of the answer
vector<reference_wrapper<int>> v;
v.push_back(object);
v[0].get() = 42; // assignment needs explicit conversion of lhs to a real reference
cout << "the answer is " << object << endl;
return 0;
}

( Example live here )

现在有人可能会争论为什么在指针周围使用像 std::reference_wrapper 这样的包装器也可以直接使用指针。 IMO 指针,具有成为 nullptr 的能力,改变了代码的语义:当你有一个原始指针时,它可能是无效的。当然,您可以假设它不是,或者将其放在注释的某个地方,但最终您会依赖代码无法保证的东西(这种行为通常会导致错误)。

如果您的 vector 元素可以“引用”对象或无效,那么原始指针仍然不是首选(对我而言):当您使用 vector 中的元素时是有效的,那么它所引用的对象实际上是从你的代码中的多个地方引用的;它是共享的。对象的“主要”引用应该是 std::shared_ptr和 vector 的元素 std::weak_ptr秒。然后,您可以(线程安全)在需要时获取有效的“引用”(共享指针)并在完成后将其删除:

auto object = make_shared<int>(42);
vector<weak_ptr<int>> v;
v.push_back (object);

// ... somewhere later, potentially on a different thread
if (auto ref = v[0].lock()) {
// noone "steals" the object now while it's used here
}
// let them do what they want with the object, we're done with it ...

最后,请对我的回答持保留态度,其中大部分是基于我的意见(和经验),可能不算作“标准做法”。

关于c++ - 仅使用标准库创建 "Vector of References"的标准实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32105092/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com