如何在不调用copy-constructor的情况下向vector添加元素?

时间:2015-05-11 06:31:55

标签: c++ c++11 vector copy-constructor move-semantics

由于某些原因,我的临时本地对象在添加到向量时总是被复制构造/销毁,这会导致由于嵌套std::reference_wrapper导致的问题,这些问题由于之后的复制构造和破坏而变得无效({{ 1}}目标位于被销毁的对象内部 - >因此,如果源对象被销毁,它们在复制构造的对象中是无效的。但是如果可能的话我想要完全避免额外的复制/销毁 - 这似乎是不可能的,因为无论我尝试过什么,它都想调用复制构造函数(甚至使用std::reference_wrapper)。

考虑到这个简单的例子(为了更容易理解而不涉及std::vector::emplace_back),它总是试图调用复制构造函数 - 我不明白为什么。

std::reference_wrapper

我在这里缺少什么想法?

1 个答案:

答案 0 :(得分:2)

根据Visual Studio 2013 documentation,强调我的:

  

“Rvalue references v3.0”在某些条件下为自动生成移动构造函数和移动赋值运算符添加了新规则。但是,由于时间和资源限制,在Visual Studio 2013中的Visual C ++中未实现

Visual Studio 2013被指定为使用Rvalue引用v2.1。

注意:作为评论中的T.C.注释,在示例中明确禁用复制构造函数也存在问题。每cppreference.com

  

如果没有为类类型(struct,class或union)提供用户定义的移动构造函数,并且满足以下所有条件:

     
      
  • 没有用户声明的复制构造函数
  •   
  • 没有用户声明的副本分配运算符
  •   
  • 没有用户声明的移动分配操作符
  •   
  • 没有用户声明的析构函数
  •   
  • (直到C ++ 14)由于下一节中详述的条件,隐式声明的移动构造函数未定义为已删除
  •   
     

然后编译器将一个移动构造函数声明为其类的内联公共成员,其签名为T :: T(T&&)。

     

一个类可以有多个移动构造函数,例如T :: T(const T&&)和T :: T(T&&)都是。如果存在一些用户定义的移动构造函数,则用户仍可以使用关键字default强制生成隐式声明的移动构造函数。

这意味着您的示例代码也会阻止自动生成移动构造函数(即,具有用户声明的复制构造函数)。

您需要显式声明移动构造函数和/或移动赋值运算符。以下适用于您的示例。

class A
{
public:
    A(int a) : a(a) {}

    A(const A&) = delete;

    A(A&& other) : a(other.a) {}

    int getInt() const { return a; }

private:
    int a;
};

int main(int argc, char* argv[])
{
    std::vector<A> vec;
    vec.emplace_back(3);
    vec.push_back(A(3));
    vec.push_back(std::move(A(3)));

    return 0;
}