vig*_*990 17 c++ vector c++11 emplace
我有一个类,其副本构造函数被显式删除(因为A在内部使用指针,我不想陷入浅层复制陷阱):
class A {
public:
A(const A&) = delete;
A& operator=(const A&) = delete;
A(const B& b, const C& c);
}
Run Code Online (Sandbox Code Playgroud)
现在我有一个类型的向量,vector<A> aVector;我想在其中插入元素 - 所以我使用emplace_back:
aVector.emplace_back(b, c);
Run Code Online (Sandbox Code Playgroud)
但是,这无法使用gcc编译,我收到错误 -
third-party/gcc-4.7.1-glibc-2.14.1/libgcc/libgcc-4.7.1/afc21dc/include/c++/4.7.1/bits/stl_construct.h: In instantiation of 'void std::_Construct(_T1*, _Args&& ...)
third-party/gcc-4.7.1-glibc-2.14.1/libgcc/libgcc-4.7.1/afc21dc/include/c++/4.7.1/bits/stl_uninitialized.h:77:3: required from 'static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator)
third-party/gcc-4.7.1-glibc-2.14.1/libgcc/libgcc-4.7.1/afc21dc/include/c++/4.7.1/bits/stl_uninitialized.h:119:41: required from '_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator)
third-party/gcc-4.7.1-glibc-2.14.1/libgcc/libgcc-4.7.1/afc21dc/include/c++/4.7.1/bits/stl_uninitialized.h:260:63: required from '_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&)
third-party/gcc-4.7.1-glibc-2.14.1/libgcc/libgcc-4.7.1/afc21dc/include/c++/4.7.1/bits/stl_uninitialized.h:283:67: required from '_ForwardIterator std::__uninitialized_move_if_noexcept_a(_InputIterator, _InputIterator, _ForwardIterator, _Allocator&)
third-party/gcc-4.7.1-glibc-2.14.1/libgcc/libgcc-4.7.1/afc21dc/include/c++/4.7.1/bits/vector.tcc:410:6: required from 'void std::vector<_Tp, _Alloc>::_M_emplace_back_aux(_Args&& ...)
third-party/gcc-4.7.1-glibc-2.14.1/libgcc/libgcc-4.7.1/afc21dc/include/c++/4.7.1/bits/vector.tcc:102:4: required from 'void std::vector<_Tp, _Alloc>::emplace_back(_Args&& ...)
Run Code Online (Sandbox Code Playgroud)
这个错误的原因是什么,如何在不删除复制构造函数的情况下修复它?我是否需要移动构造函数 - 是否需要明确定义?
Evg*_*yuk 21
你应该添加移动构造函数 - 因为std::vector::emplace_back可能需要复制/移动构造函数的重定位.或者只是使用std::deque.
#include <vector>
#include <deque>
using namespace std;
struct NoCopyNoMove
{
NoCopyNoMove(const NoCopyNoMove&) = delete;
NoCopyNoMove& operator=(const NoCopyNoMove&) = delete;
NoCopyNoMove(NoCopyNoMove&&) = delete;
NoCopyNoMove& operator=(NoCopyNoMove&&) = delete;
NoCopyNoMove(int){};
};
struct OnlyMove
{
OnlyMove(const OnlyMove&) = delete;
OnlyMove& operator=(const OnlyMove&) = delete;
OnlyMove(OnlyMove&&) noexcept {}
OnlyMove& operator=(OnlyMove&&) noexcept {}
OnlyMove(int){};
};
int main()
{
deque<NoCopyNoMove> x;
x.emplace_back(1);
vector<OnlyMove> y;
y.emplace_back(1);
}
Run Code Online (Sandbox Code Playgroud)
§23.2.3表101 - 可选的序列容器操作
a.emplace_back(args)[...]要求:
T应从argsEmplaceConstructible进入X.因为vector,T也应该MoveInsertable进入X.
错误不是emplace_back的错误.要将对象放在向量中,它必须是可移动的或可复制的.如果您实际运行了实现了复制构造函数的代码,您会注意到它永远不会被调用.这是cppreference.com上的一个条目

我要做的是修复这个是实现移动构造函数,这使得它编译,我看不出有任何移动构造函数的任何缺点.和cctor一样,移动构造函数不会在当前代码中调用.