如何在不调用复制构造函数的情况下向向量添加元素?
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;
}
出于某种原因,我的临时本地对象在添加到向量时总是 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;
}