c++ - 为什么 gcc 6.4.0 c++14 会自动将左值移动到右值
问题描述
我遇到了 gcc 编译器将局部变量(不是临时的)作为右值参数移动到函数的问题。我有一个简单的例子:
class A
{
public:
A() {}
A& operator=(const A&) { std::cout << "const A&\n"; return *this; }
A& operator=(A&&) { std::cout << "A&&\n"; return *this; }
};
class B
{
public:
B() {}
B& operator=(const B&) { std::cout << "const B&\n"; return *this; }
B& operator=(B&&) { std::cout << "B&&\n"; return *this; }
template<class T> B& operator=(const T&) { std::cout << "const T& (T is " << typeid(T).name() << ")\n"; return *this; }
template<class T> B& operator=(T&&) { std::cout << "T&& (T is " << typeid(T).name() << ")\n"; return *this; }
};
int main(int argc, char **argv)
{
A a1;
A a2;
a1 = a2;
B b1;
B b2;
std::cout << "B is " << typeid(B).name() << "\n";
b1 = b2;
}
输出:
const A&
B is 1B
T&& (T is 1B)
我没想到它,因为移动赋值将右值归零。在我的情况下,它导致崩溃,因为在 b1=b2; 之后使用了 b2;
问题是为什么会发生。
解决方案
template<class T> B& operator=(T&&)
{ std::cout << "T&& (T is " << typeid(T).name() << ")\n"; return *this; }
不是移动赋值运算符,因为它是一个模板。来自 N4140,[class.copy]/19
用户声明的移动赋值运算符
X::operator=
是类的非静态非模板成员函数,X
只有一个类型为X&&
、const X&&
、volatile X&&
或的参数const volatile X&&
。
您已经定义了一个接受转发引用的赋值运算符模板。在行
b1 = b2;
operator=(T&&)
模板比复制赋值运算符 ( ) 更匹配,因为B& operator=(const B&)
将T
被推断为B&
并且不需要const
限定转换。
如果你用 Boost.TypeIndex 替换对 的调用typeid
,它会丢弃引用,这会变得很明显。
template<class T> B& operator=(T&&)
{
std::cout << "T&& (T is " << boost::typeindex::type_id_with_cvr<T>().pretty_name() << ")\n";
return *this;
}
输出变为
const A&
B is B
T&& (T is B&)
如果您不想operator=(T&&)
被选中,则可以对其进行约束,以便在以下情况下将其从重载决议中删除T=B
template<class T, std::enable_if_t<not std::is_same<B, std::decay_t<T>>{}, int> = 0>
B& operator=(T&&)
{
std::cout << "T&& (T is " << boost::typeindex::type_id_with_cvr<T>().pretty_name() << ")\n";
return *this;
}
(如果涉及继承,您可能希望使用is_convertible
而不是)is_same
推荐阅读
- json - 从 URL 反序列化 JSON - 如何将其添加到多个对象
- python-3.x - 如何使用 tkinter 打开然后关闭外部窗口
- python - 为什么我的表单会生成 KeyError 而不是从表单中引发 ValidationError?
- rust - 不能使用入口 API 使用引用作为函数内部的键来改变 HashMap
- windows - 命令提示符不会自行刷新
- tensorflow - tf.keras.backend 和 tensorflow 库中的冗余
- tensorflow - OOm - 尽管减少了批量大小,但仍无法运行 StyleGAN2
- c++ - 试图找出为什么我的代码一直在无限循环
- python - python - 如何计算python文本文件中相同关键字出现2次的行数?
- python - 如何使用 Python 和 Flask 呈现带有两个列表的 jinja html 列表?