【问题标题】:How can I use vector with a reference type instance object in C++11?如何在 C++11 中将向量与引用类型实例对象一起使用?
【发布时间】:2013-06-06 06:19:51
【问题描述】:

在 C++11 中是否可以有没有可复制对象(具有引用实例)的 std::vector ?

struct CanNotCopy {
  int& intref_;
  CanNotCopy(int& i) noexcept : intref_(i) {}
  // How do I make move constructor and operator = ?
};

std::vector<CanNotCopy> hoge; // OK
hoge.resize(10); // default constructor required
int j = 123;
hoge[1] = CanNotCopy(j);  // copy constructor required

【问题讨论】:

  • 如果对象可以移动就足够了。但是,CanNotCopy 类既不是 copyable 也不是 movable,因此它不能用作std::vector 的元素类型。
  • 另外,如果你没有默认构造函数(注意不可移动类当然可以有默认构造函数;但是你的类没有),你必须告诉resize如何构造新的对象。不幸的是,这样做的唯一方法是将对象提供给 copy ,因此您不能将 resize 与既不是默认构造也不是复制构造的类一起使用。
  • 澄清一下,CanNotCopy 类型既可以复制构造也可以移动构造。第二个有问题的行要求类型是可移动的。引用成员会干扰赋值运算符,但不会干扰复制和移动构造函数。 (不可分配确实会阻止该类型被视为可复制或可移动。)

标签: c++ c++11


【解决方案1】:

来自std::vector,描述T

对元素的要求取决于对容器执行的实际操作。一般要求元素类型满足 MoveConstructible 和 MoveAssignable 的要求,但很多成员函数的要求更严格。

CanNotCopy 不可移动或复制,因此不能用作T

部分解决方案是使用std::reference_wrapper&lt;CanNotCopy&gt; 作为元素类型(可复制但不可默认构造):

...是一个类模板,它将引用包装在可复制、可分配的对象中。它经常被用作在标准容器(如 std::vector 或 std::pair)中存储引用的机制,这些容器通常不能保存引用。

例如:

std::vector<std::reference_wrapper<CanNotCopy>> hoge;
int j = 19;
CanNotCopy c(j);
hoge.push_back(std::ref(c));
std::cout << hoge[0].get().intref_ << "\n";

resize() 不适用于 std::reference_wrapper&lt;CanNotCopy&gt;,因为它不是默认可构造的。但是,此解决方案是脆弱的,因为在 CanNotCopy 引用的 CanNotCopy 实例中引用的 int 存在生命周期依赖关系,存在悬空引用的风险。

一种解决方案是使用std::unique_ptr&lt;CanNotCopy&gt; 作为元素类型(可移动且默认可构造):

std::vector<std::unique_ptr<CanNotCopy>> hoge;
hoge.resize(5);
int j = 19;
hoge[1].reset(new CanNotCopy(j));
std::cout << hoge[1]->intref_ << "\n";

CanNotCopy 中对 int 引用的生命周期依赖仍然存在。

【讨论】:

    【解决方案2】:

    直截了当,允许vector&lt;CanNotCopy&gt;

    struct CanNotCopy {
      int& intref_;
      CanNotCopy (CanNotCopy && from) : intref_(from.intref_) { }
    };
    

    这当然允许您将对象移入和移出向量,但不能创建副本或创建默认构造的元素。我不知道类的语义,特别是我不知道intref_ 是什么意思。你也必须在默认的ctor中初始化它,所以我不能为你写。

    【讨论】:

      【解决方案3】:

      可以通过使用std::optional/boost::optional 包装器来实现。第二个需要使用in-place factories 来实现所需的行为。

      【讨论】:

        【解决方案4】:

        我有同样的问题,已经很好地回答了here:使用std::vector::emplace_back

        【讨论】:

          猜你喜欢
          • 2014-01-02
          • 1970-01-01
          • 1970-01-01
          • 2013-12-07
          • 2014-02-03
          • 2018-04-23
          • 1970-01-01
          • 2014-09-18
          • 1970-01-01
          相关资源
          最近更新 更多