我最近在我的C++11代码中遇到了一些奇怪的行为。
我有一个类,只能移动:
class only_move
{
public:
only_move() : value(0) {}
only_move(int value) : value(value) {}
only_move(const only_move&) = delete;
only_move& operator=(const only_move&) = delete;
only_move(only_move&&) = default;
only_move& operator=(only_move&&) = default;
int value;
};
我还有一个类,其中包含一个only_move
对象:
class has_only_move_member
{
public:
has_only_move_member() = delete;
has_only_move_member(only_move&& value) : member(std::move(value)) {}
only_move member;
};
如果我理解正确的话,这意味着has_only_move_member
不能被复制,因为only_move
成员不能被复制。这意味着has_only_move_member(const has_only_move_member&)
会被隐式删除。我们来检查一下:
has_only_move_member object(only_move(5));
has_only_move_member copy_of_object(object);
如预期的一样,它会输出:
error: use of deleted function ‘has_only_move_member::has_only_move_member(const has_only_move_member&)’
note: ‘has_only_move_member::has_only_move_member(const has_only_move_member&)’ is implicitly deleted because the default definition would be ill-formed:
class has_only_move_member
好的,我继续操作并把has_only_move_member
实例放入了一个std::map
中。由于它们没有拷贝构造函数,所以我把它们移动到了里面:
has_only_move_member object(only_move(5));
std::map<int, has_only_move_member> data;
data.emplace(5, std::move(object));
到目前为止,一切都很好。这个功能非常好用。
但是我有一个想法。如果更加明确地删除has_only_move_member
的拷贝构造函数怎么样呢?所以我在类has_only_move_member
中进行了编写:
has_only_move_member(const has_only_move_member&) = delete;
接着上面的代码,在我将对象移动到一个映射中时出现了错误:
/usr/include/c++/4.8/bits/stl_pair.h:134:45: error: use of deleted function ‘has_only_move_member::has_only_move_member(const has_only_move_member&)’
当然,它被删除了,但为什么隐式删除和显式删除之间存在如此大的差距呢?
我在Debian上使用g++ 4.8.2和clang 3.4-rc1以及libstdc++和最近的apple-clang-llvm 4.0在Mac OS X 10.9上使用libc++时得到了相同的行为。