如何在不调用复制构造函数的情况下向向量添加元素?

How to add elements to vector without invoking copy-constructor?

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

考虑到这个简单的示例(为了在不涉及 std::reference_wrapper 的情况下更容易理解),它总是尝试调用复制构造函数 - 我不明白为什么。

#include <vector>

class A{
public:
  A(int a) : a(a){ }
  int getInt() const{ return a; }
  A(const A&) = delete; /* to deny copy-construction */
private:
  int a;
};

int main(int argc, char* argv[]){
  std::vector<A> vec;
  vec.emplace_back(3);              /* tries to call copy constructor */
  vec.push_back(A(3));              /* tries to call copy constructor */
  vec.push_back(std::move(A(3)));   /* tries to call copy constructor */
  return 0;
}

知道我在这里遗漏了什么吗?

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

"Rvalue references v3.0" adds new rules to automatically generate move constructors and move assignment operators under certain conditions. However, this is not implemented in Visual C++ in Visual Studio 2013, due to time and resource constraints.

Visual Studio 2013 指定为使用右值引用 v2.1.

注:T.C. notes in the comments there is also an issue with explicitly disabling the copy constructor in your example. Per cppreference.com.

If no user-defined move constructors are provided for a class type (struct, class, or union), and all of the following is true:

  • there are no user-declared copy constructors
  • there are no user-declared copy assignment operators
  • there are no user-declared move assignment operators
  • there are no user-declared destructors
  • (until C++14) the implicitly-declared move constructor is not defined as deleted due to conditions detailed in the next section

then the compiler will declare a move constructor as an inline public member of its class with the signature T::T(T&&).

A class can have multiple move constructors, e.g. both T::T(const T&&) and T::T(T&&). If some user-defined move constructors are present, the user may still force the generation of the implicitly declared move constructor with the keyword default.

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

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

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;
}