隐式和显式删除的复制构造函数

7

我最近在我的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++时得到了相同的行为。


4
您添加了一个自定义构造函数(即使它是被删除掉的)。因此它不会自动生成移动构造函数。然后它退而求其次进行复制,但显然无法这样做。 - John5342
哦,我真丢脸。我怎么会忘记这个了?;-(谢谢。 - Mario
1个回答

10

我在评论中已经说过这一点,但既然这是一个正确的答案,我现在把它贴出来:

你添加了一个自定义构造函数(即使它是一个被删除的构造函数)。因此编译器不会自动生成移动构造函数。编译器然后退而求其次进行复制,而你又明确要求不能复制,所以编译器无法完成操作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接