C++ C++;复制、移动构造函数

C++ C++;复制、移动构造函数,c++,c++11,copy-constructor,move-constructor,C++,C++11,Copy Constructor,Move Constructor,我这里有代码: #include <string> #include <iostream> #include <initializer_list> template <typename T> class Test { public: Test(std::initializer_list<T> l) { std::cout << __PRETTY_FUNCTION__ << std::endl;

我这里有代码:

#include <string>
#include <iostream>
#include <initializer_list>

template <typename T>
class Test
{
public:
  Test(std::initializer_list<T> l)
  {
    std::cout << __PRETTY_FUNCTION__ << std::endl;
  }

  Test(const Test<T>& copy)
  {
    std::cout << __PRETTY_FUNCTION__ << std::endl;
  }
  Test(Test&&) = delete;
  Test() = delete;
};

void f(const Test<Test<std::string>>& x)
{
  std::cout << __PRETTY_FUNCTION__ << std::endl;
}

void f(const Test<std::string>& x)
{
  std::cout << __PRETTY_FUNCTION__ << std::endl;
  f(Test<Test<std::string>>{x});
}

int main()
{
  Test<std::string> t1 {"lol"};
  f(t1);
  return 0;
}
#包括
#包括
#包括
模板
课堂测试
{
公众:
测试(标准::初始值设定项\u列表l)
{
标准::cout
我一直认为move和copy构造函数在编译方面是等价的,因为rvalue可以绑定到const引用,但是在重载解析中,显式定义rvalue引用的重载只是优先考虑

您的假设是正确的。如果您有一个重载集,它采用
常量&
&
如果您有一个右值,
&&
版本将优先于
常量&
。这里的问题是您的
&
版本被标记为已删除。这意味着您明确表示您不想删除要从临时文件中构造,代码将无法编译

在这种情况下,如果您不希望类是可移动的,那么您可以直接删除它

Test(Test&&) = delete;

由于用户定义的复制构造函数的存在将删除编译器自动生成的移动构造函数。

您明确声明了移动构造函数,并将其标记为
delete
,将通过重载解析选择它,然后导致错误

如果同时提供了复制和移动构造函数,并且没有其他构造函数可用,则重载解析会在参数是相同类型的右值(如std::move
的结果的xvalue或如无名临时值(直到C++17)
的prvalue)时选择移动构造函数,如果参数是左值(命名对象或返回左值引用的函数/运算符),则选择复制构造函数

请注意,重载解析会忽略,但显式声明的不会忽略

重载解析将忽略已删除的隐式声明的移动构造函数(否则将阻止从右值进行复制初始化)。(自C++14)


声明了一个
delete
d函数。它将在名称查找期间包含在重载集中,因此您实际上正在尝试调用
delete
d函数。如果您定义了一个复制构造函数,而根本没有声明移动构造函数,您将获得预期的行为。@BoBTFish在这种情况下,我的类将具有move d定义原因编译器将为我生成它,我将有一个。使用“删除”命令,我禁止编译器生成一个。如果您有用户定义的复制构造函数,这将禁止编译器提供移动构造函数。
Test(Test&&) = delete;