使用 const 对象移动语义
move semantics with const object
我有这样的代码:
class Pair{
public:
Pair(Pair && other){};
Pair(Pair & other){};
};
class IROList{
public:
virtual const Pair get(const char *key) const = 0;
inline const Pair operator[](const char *key) const{
return this->get(key);
// error: binding ‘const Pair’ to reference of type ‘Pair&&’ discards qualifiers
}
};
编译时,生成
error: binding ‘const Pair’ to reference of type ‘Pair&&’ discards qualifiers
如果我将移动构造函数更改为 const,错误就会消失。
Pair(const Pair && other){};
但是,如果移动构造函数采用const,我就无法真正移动数据。我应该复制它。
除了删除返回方法的 const 之外,是否有任何解决方法,例如
virtual Pair get(const char *key) const = 0;
inline Pair operator[](const char *key) const;
您不能移动 const
对象,因为移动操作是一种修改。当您移动时,您将旧对象的内容交换到新对象中。这又将新对象的不确定值放入旧对象中。如果旧对象是 const
,则无法执行此操作,因为您将无法写入它。
当您使用移动语义时,您希望按值传递。当您按值传递时,您会创建一个永远不会被访问的副本,因此您可以自由地从它移动。参见:Is pass-by-value a reasonable default in C++11?
问题是你没有很好地实现你的拷贝构造函数。
而不是:
Pair(const Pair & other){};
你写了
Pair(Pair & other){};
这会导致构造函数只接受左值变量,而不接受临时变量,因为只有 const 引用可以绑定到临时变量和右值引用。
这会强制编译器 return 将 get 作为 r 值引用(移动语义)配对,因为它 return 是临时的,它不知道如何复制它,只是如何移动它。同样,只能通过 const 引用或 r-value-reference 捕获临时文件。
r-value-references 不是 const - 这是它们的全部存在!被抓住,他们的内容将被另一个对象窃取。
为了证明我的观点,这里是 GCC 编译器输出你的代码(无常量):
http://coliru.stacked-crooked.com/a/c390189089434f30 - 不编译
和const:
http://coliru.stacked-crooked.com/a/0db0fc767e6f10f2 - 没有编译器错误。
除此之外,我建议您查看 std::map
实施或类似 类。开发人员之间就 operator []
应该是什么样子、return 应该是什么样子以及为什么这样达成了一些共识。
良好的软件设计远比移动语义等非常具体的功能重要。
Is there any workaround except removing the const of returning methods
没有。在这种情况下返回 const
值是愚蠢且毫无意义的,因为用户可以随意制作一个可变副本。您只能通过使其成为 const
.
来禁止优化和良好的语义(例如移动语义)
删除 const
不是 "workaround",这是无论移动语义问题如何都应该做的事情。
我有这样的代码:
class Pair{
public:
Pair(Pair && other){};
Pair(Pair & other){};
};
class IROList{
public:
virtual const Pair get(const char *key) const = 0;
inline const Pair operator[](const char *key) const{
return this->get(key);
// error: binding ‘const Pair’ to reference of type ‘Pair&&’ discards qualifiers
}
};
编译时,生成
error: binding ‘const Pair’ to reference of type ‘Pair&&’ discards qualifiers
如果我将移动构造函数更改为 const,错误就会消失。
Pair(const Pair && other){};
但是,如果移动构造函数采用const,我就无法真正移动数据。我应该复制它。
除了删除返回方法的 const 之外,是否有任何解决方法,例如
virtual Pair get(const char *key) const = 0;
inline Pair operator[](const char *key) const;
您不能移动 const
对象,因为移动操作是一种修改。当您移动时,您将旧对象的内容交换到新对象中。这又将新对象的不确定值放入旧对象中。如果旧对象是 const
,则无法执行此操作,因为您将无法写入它。
当您使用移动语义时,您希望按值传递。当您按值传递时,您会创建一个永远不会被访问的副本,因此您可以自由地从它移动。参见:Is pass-by-value a reasonable default in C++11?
问题是你没有很好地实现你的拷贝构造函数。
而不是:
Pair(const Pair & other){};
你写了
Pair(Pair & other){};
这会导致构造函数只接受左值变量,而不接受临时变量,因为只有 const 引用可以绑定到临时变量和右值引用。
这会强制编译器 return 将 get 作为 r 值引用(移动语义)配对,因为它 return 是临时的,它不知道如何复制它,只是如何移动它。同样,只能通过 const 引用或 r-value-reference 捕获临时文件。
r-value-references 不是 const - 这是它们的全部存在!被抓住,他们的内容将被另一个对象窃取。
为了证明我的观点,这里是 GCC 编译器输出你的代码(无常量):
http://coliru.stacked-crooked.com/a/c390189089434f30 - 不编译
和const:
http://coliru.stacked-crooked.com/a/0db0fc767e6f10f2 - 没有编译器错误。
除此之外,我建议您查看 std::map
实施或类似 类。开发人员之间就 operator []
应该是什么样子、return 应该是什么样子以及为什么这样达成了一些共识。
良好的软件设计远比移动语义等非常具体的功能重要。
Is there any workaround except removing the const of returning methods
没有。在这种情况下返回 const
值是愚蠢且毫无意义的,因为用户可以随意制作一个可变副本。您只能通过使其成为 const
.
删除 const
不是 "workaround",这是无论移动语义问题如何都应该做的事情。