使用 std::move 时运动构造函数与其他非运动构造函数发生冲突导致 C++ 编译错误

C++ compiling error due to a conflict between the movement constructor and other non-movement one when using std::move

我正在用移动语义做一些 "experiments" 以便完全理解它。我已经到了我完全不明白的地步。这是因为在使用std::move的时候,好像和A::A(B b)A::A(B &&b)这样的构造函数有冲突。下面是对此进行解释的代码:

struct Item {
    Item() { }

    Item(const Item &other) {
        std::cout << "Item::Item(const Item& )\n";
    }
};

struct Container {
    Container(Item i) {
        std::cout << "Container::Container(Item )\n";
    }

    Container(Item &&i) {
        std::cout << "Container::Container(Item&& )\n";
    }
};

int main() {
    Item i;
    Container c(std::move(i));
    return 0;
}

尝试编译以上代码时,出现以下错误:

error C2668: 'Container::Container' : ambiguous call to overloaded function
1>          c:\users\xe74139\documents\visual studio 2012\projects\project1\project1\maincpp.cpp(21): could be 'Container::Container(Item &&)'
1>          c:\users\xe74139\documents\visual studio 2012\projects\project1\project1\maincpp.cpp(17): or       'Container::Container(Item)'

我知道构造函数 Container(Item i) 根本没有意义,但我仍然不明白为什么 C++ 编译器会发现两个 Container 构造函数之间存在冲突。

为什么不能确定Container c(i)是调用Container(Item)Container c(std::move(i))是调用Container(Item &&)

编辑: 或者,换句话说,为什么构造函数 Container(Item)Container c(std::move(i))?

这样的调用有效

据我所知,这是因为参数先求值,然后通过。一旦通过,它就是任何 r-value,并且您的两个构造函数都可以工作。我不确定是否可能有这样的过载,从我的角度来看这没有意义。

为什么不呢?好吧,您正在尝试定义一个强制元素移动的容器。从设计的角度来看,您必须考虑到使用该代码的人可能不想要数据 "stolen"(已移动)。我认为在这种情况下更有意义:

struct Item {
    Item() { }

    Item(const Item &other) {
        std::cout << "Item::Item(const Item& )\n";
    }
    Item(Item &&other) {
        std::cout << "Item::Item(Item&&)\n";
    }
};

此重载更有意义 - 您将明确说明何时移动和复制对象(此处有默认 move,但这种方式使其更明显)。现在你只需要

Container(Item i);

(没有其他构造函数)并用

调用它
Container c(std::move(i));

是我们所期望的 - 而不是复制 i,您明确表示您希望它移动,i 负责处理这个问题。

Why the constructor Container(Item) is valid for a call like Container c(std::move(i))?

因为当给定 std::move(i)(这是一个 Item&&)的结果时,您可以构造一个 Item

就像 HowardHinnant 在评论中所说的那样 - ItemItem& 是一样的 - 你可以在传递另一个时构造一个,所以如果你定义了这两个构造函数,你就已经造成歧义。