用const对象移动语义

时间:2015-07-17 17:38:48

标签: c++ c++11 move-semantics

我有这样的代码:

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;

3 个答案:

答案 0 :(得分:5)

问题是你没有很好地实现你的拷贝构造函数。

而不是:

Pair(const Pair & other){};
你写了

Pair(Pair & other){};

这会导致构造函数只接受l值变量,而不接受临时值,因为只有const引用可以绑定到temporaries和r值引用。

这会强制编译器从get返回Pair作为r值引用(移动语义),因为它返回一个临时的,它不知道如何复制它,只知道如何移动它。再次,临时只能通过const引用或r值引用来捕获。

r-value-references不是const - 这是他们的全部存在!将被抓住,他们的内容将被另一个对象窃取。

为了证明我的观点,这里是GCC编译器输出与你的代码(没有const):
http://coliru.stacked-crooked.com/a/c390189089434f30 - 无法编译

和const:
http://coliru.stacked-crooked.com/a/0db0fc767e6f10f2 - 没有编译错误。

除此之外,我建议你看看std::map实现或类似的类。开发人员之间就operator []应该是什么样子以及它返回的原因和原因有一些协议。 良好的软件设计比移动sematincs等非常具体的功能更为重要。

答案 1 :(得分:1)

  

除了删除返回方法的常量

之外是否有任何解决方法?

没有。在这种情况下返回const值是愚蠢而毫无意义的,因为用户可以随意制作可变副本。您只能通过使const禁止优化和良好的语义(例如移动语义)。

删除const不是“解决方法”,无论移动语义是什么问题,都应该做什么。

答案 2 :(得分:0)

您无法移动const对象,因为移动操作是一种修改。移动时,将旧对象的内容交换为新对象。这反过来又将新对象的不确定值放入旧对象中。如果旧对象为const,则无法执行此操作,因为您无法写入该对象。

当您使用移动语义时,您希望按值传递。当您通过值传递时,您将制作一个永远不会被访问的副本,以便您可以自由地移动它。请参阅:Is pass-by-value a reasonable default in C++11?