C++ 不会通过取消注释移动运算符来编译
C++ does not compile by uncommenting move operator
我有以下代码:
template <typename T>
struct X {
X() : x(5) {}
template <template <typename> class S>
X(const S<T> & y) : x(y.x) {}
// Uncomment and it does not compile anymore
// X(X&& z) : x(z.x) {}
T x;
};
int main ()
{
X<int> y;
auto x = y;
return 0;
}
你能解释一下为什么一旦取消注释指定的代码就无法编译吗?
复制构造函数被隐式声明为已删除,因为您声明了一个移动构造函数。
添加一个默认的(或用户定义的)复制构造函数,它可以正常编译:
X(const X<T>&)=default;
Humam Helfawi 明白了。
我试着完成他的回答。
Svalorzen:看这段代码
#include <iostream>
template <typename T>
struct X {
X() : x(5) {}
template <template <typename> class S>
X (const S<T> & y) : x(y.x)
{ std::cout << "templated constructor" << std::endl; }
X (const X<T> & y) : x(y.x)
{ std::cout << "copy constructor" << std::endl; }
T x;
};
int main ()
{
X<int> y;
auto x = y;
return 0;
}
输出为"copy constructor"。
当编译器找到匹配的模板函数和匹配的普通(无模板)函数时,选择普通函数作为更具体的函数。
现在删除复制构造函数的定义
#include <iostream>
template <typename T>
struct X {
X() : x(5) {}
template <template <typename> class S>
X (const S<T> & y) : x(y.x)
{ std::cout << "templated constructor" << std::endl; }
T x;
};
int main ()
{
X<int> y;
auto x = y;
return 0;
}
你得到了没有移动构造函数但添加了 cout ("templated constructor") 的示例。
可以看到输出是空的
那是因为编译器选择了作为默认版本隐式存在的复制构造函数。
添加移动构造函数时,顺便将复制构造函数标记为已删除。但是复制构造函数一直存在(即使标记为已删除)并且编译器会考虑它。因此,当编译器尝试实现 "x = y" 时,匹配您的模板构造函数,匹配复制构造函数,选择复制构造函数(更具体),看到它被删除并给出错误。
当你添加
X (const X<T> &) = default;
您允许编译器使用复制构造函数。
p.s.: 抱歉我的英语不好
我有以下代码:
template <typename T>
struct X {
X() : x(5) {}
template <template <typename> class S>
X(const S<T> & y) : x(y.x) {}
// Uncomment and it does not compile anymore
// X(X&& z) : x(z.x) {}
T x;
};
int main ()
{
X<int> y;
auto x = y;
return 0;
}
你能解释一下为什么一旦取消注释指定的代码就无法编译吗?
复制构造函数被隐式声明为已删除,因为您声明了一个移动构造函数。
添加一个默认的(或用户定义的)复制构造函数,它可以正常编译:
X(const X<T>&)=default;
Humam Helfawi 明白了。
我试着完成他的回答。
Svalorzen:看这段代码
#include <iostream>
template <typename T>
struct X {
X() : x(5) {}
template <template <typename> class S>
X (const S<T> & y) : x(y.x)
{ std::cout << "templated constructor" << std::endl; }
X (const X<T> & y) : x(y.x)
{ std::cout << "copy constructor" << std::endl; }
T x;
};
int main ()
{
X<int> y;
auto x = y;
return 0;
}
输出为"copy constructor"。
当编译器找到匹配的模板函数和匹配的普通(无模板)函数时,选择普通函数作为更具体的函数。
现在删除复制构造函数的定义
#include <iostream>
template <typename T>
struct X {
X() : x(5) {}
template <template <typename> class S>
X (const S<T> & y) : x(y.x)
{ std::cout << "templated constructor" << std::endl; }
T x;
};
int main ()
{
X<int> y;
auto x = y;
return 0;
}
你得到了没有移动构造函数但添加了 cout ("templated constructor") 的示例。
可以看到输出是空的
那是因为编译器选择了作为默认版本隐式存在的复制构造函数。
添加移动构造函数时,顺便将复制构造函数标记为已删除。但是复制构造函数一直存在(即使标记为已删除)并且编译器会考虑它。因此,当编译器尝试实现 "x = y" 时,匹配您的模板构造函数,匹配复制构造函数,选择复制构造函数(更具体),看到它被删除并给出错误。
当你添加
X (const X<T> &) = default;
您允许编译器使用复制构造函数。
p.s.: 抱歉我的英语不好