我有一个类,其副本构造函数被显式删除(因为A在内部使用指针,我不想陷入浅层复制陷阱):
class A {
public:
A(const A&) = delete;
A& operator=(const A&) = delete;
A(const B& b, const C& c);
}
现在我有一个vector<A> aVector;
类型的向量,我想在其中插入元素 - 所以我使用emplace_back
:
aVector.emplace_back(b, c);
然而,这无法使用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&& ...)
出现此错误的原因是什么?如何在不删除复制构造函数的情况下修复此错误?我是否需要移动构造函数 - 是否需要明确定义?
答案 0 :(得分:20)
您应该添加移动构造函数 - 因为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);
}
§23.2.3表101 - 可选的序列容器操作
a.emplace_back(args)
[...]要求:
T
必须EmplaceConstructible
从X
进入args。对于vector
,T
也应为MoveInsertable
X
。
答案 1 :(得分:8)
错误不是emplace_back的错误。要将对象放在向量中,它必须是可移动的或可复制的。如果您实际运行了实现了复制构造函数的代码,您会注意到它永远不会被调用。这是cppreference.com上的一个条目
我要做的是修复这个是实现移动构造函数,这使得它编译,我看不出有任何移动构造函数的缺点。与cctor一样,移动构造函数不会在当前代码中调用。
答案 2 :(得分:0)
我在外部库的课程中遇到了这个问题。我到了,
"Error C2280 ClassName::ClassName(const ClassName &)': attempting to reference a deleted function"
我猜测我正在使用的课程已删除其副本构造函数。我无法将它添加到我知道的任何std
容器中,用于我的自定义派生类对象,它们使用我的一些帮助程序包装它们的对象以帮助进行初始化/错误检查。
我使用( 冒险 )指针解决了这个阻止程序。
基本上,我转到了这个:
std::vector<ClassName*> names;
ClassName name("arg");
ClassName name_ptr = &name;
names.push_back(name_ptr);
原来是这样的:
std::vector<ClassName> names;
ClassName name("arg");
names.push_back(name);
有趣的是,这是第一次用C ++进行编码,我实际上需要使用指针来解决非指针特定的使用要求,因为没有已知的替代方法。这让我担心我可能会在自己的代码中遗漏一些基本内容。
也许有更好的方法可以做到这一点,但它还没有出现在这个问题的答案列表中......
我之前应该提到这一点,谢谢aschepler; 如果你这样做,并且你使用的容器比对象寿命长, &#34;爆炸,你已经死了。&#34;
答案 3 :(得分:0)
只想添加到@kayleeFrye_onDeck's answer。我的情况与他们的情况几乎相同,并且对我有用的确切语法(基于评论中的反馈)如下:
vector< std::unique_ptr<ClassName> > names; // Declare vector of unique_ptrs of the class instance
std::unique_ptr<ClassName> name_ptr = std::make_unique<ClassName>();
names.push_back(std::move(name_ptr)); // Need to use std::move()
// Now you can access names objects without error:
names[0]->classMethod();