C++ 在向量中使用不可赋值的对象

2022-01-24 00:00:00 reference containers vector c++

我想在 std::vector 中存储一个对象列表,但是这些对象包含一个引用并且无法分配给它.但是,我可以复制构造该对象.

I want to store a list of objects in an std::vector, but the objects contain a reference and cannot be assigned to. I can, however, copy-construct the object.

我能想到的唯一选择是使用指针来包装对象并在需要分配指针时重新安装指针,但是这样做的语法会显着降低可读性,尤其是在使用迭代器时,我更喜欢另一种选择.

The only option I can think of is to use pointers to wrap the objects and reseat the pointers when they need to be assigned, but the syntax for this would significantly reduce readability, especially when using iterators, and I would prefer an alternative.

不起作用:

std::vector<MyObject> myVector;
//fill the vector
//...
myVector[1] = object1;

智能指针牺牲了可读性:

Smart pointers sacrifice readability:

std::vector<std::unique_ptr<MyObject>> ptrVector;
//fill the vector
//...
ptrVector[1] = std::unique_ptr<MyObject>(new MyObject(object1));

还有其他方法可以在 std::vector 中使用不可分配的对象吗?

Are there any other methods to use unassignable objects in an std::vector?

推荐答案

这不是您问题的直接答案,因为我无法提供 std::vector 或不同的使用方式,让您可以做您需要做的事情.

This isn't a direct answer to your question as I can't offer a replacement for std::vector, or a different way of using it that allows you to do what you need to.

但是,如果可以修改 MyObject 的定义,则可以选择将其更改为使用 std::reference_wrapper 而不是常规引用.这将允许 MyObject 是可分配的.

However, if it is possible to modify the definition of MyObject, it may be an option to change it so it uses std::reference_wrapper instead of conventional references. That would allow MyObject to be assignable.

例子:

#include <vector>
#include <functional>
#include <iostream>

struct MyObject
{
  //int &_i;
  std::reference_wrapper<int> _i;
  MyObject(int &i):_i(i) {}
};


int main() {
  std::vector<MyObject> vec;
  int i1 = 3;
  int i2 = 4;
  MyObject c1(i1);
  MyObject c2(i2);

  /* Storing object. */
  vec.push_back(c1);

  /* Assigning to it. */
  vec[0] = c2;

  /* Confirming that it's the correct object now. */
  for (const MyObject &it : vec)
    std::cout << it._i << std::endl;

  /* Modifying the value of its internal reference. */
  vec[0]._i.get() = 5;
  /* Confirming that the original int changed value indeed. */
  std::cout << "i2 == " << i2 << std::endl;

  return 0;
}

警告:现有代码可能已经包含对引用成员的直接分配(即上述代码中名为 _i 的成员).这些分配旨在更改引用所指对象的值.当用 std::reference_wrapper 替换引用时,所有直接赋值 _i = x 必须替换为 _i.get() = x,否则程序的语义会完全改变.

Caveat: Existing code may already contain direct assignments to the reference member (i.e. the member called _i in the code above). Those assignments were intended to change the value of the object the reference refers to. When replacing the reference with a std::reference_wrapper, all direct assignments _i = x must be replaced with _i.get() = x, otherwise the semantics of the program change entirely.

(编辑)如果使用的引用是 const-references const T&,则可以使用 std::reference_wrapper.使用上面的示例,MyObject 的定义随后更改为:

(EDIT) If the references used are const-references const T&, a std::reference_wrapper<const T> can be used. Using the example above, the definition of MyObject then changes to this:

struct MyObject
{
  std::reference_wrapper<const int> _i;
  MyObject(const int &i):_i(i) {}
};

相关文章