移动语义和临时隐含此

时间:2013-08-25 19:35:06

标签: c++ optimization methods move-semantics

当对象*this实际上是临时的时,是否可以创建不同的方法?

例如:

#include <iostream>

struct BigObj{
    void changeFast() {}
};

class A {
    BigObj obj;
public:
    A(){}
    A(const A& a) {
        obj = a.obj;
        std::cout << "copy\n";
    }
    A(A&& a) {
        obj = std::move(a.obj);
        std::cout << "move\n";
    }
    A changed() {
        A ret = *this; //(1)
        ret.obj.changeFast();
        return ret;
    }
};

int main(){
    A a;
    A b = std::move(a).changed();
    (void)b;
    return 0;
}

在第(1)行中我们有副本,但并不是真的需要。但我们不能总是搬到这里,因为有时方法不是临时的。应该怎样做才能避免复制?

如果不是方法,只是函数可以写入类似函数:

A changed(const A& a){
}

A changed(A&& a){
}

2 个答案:

答案 0 :(得分:4)

您可以在*this的r值上重载函数。例如:

class A
{
public:
    // ... 
    A changed() const&; // called for l-values
    A changed() &&;     // called for r-values
};

但是,如果没有参考资格,您不能使具有参考资格的版本超载。见13.1 [over.load]第2段,第3章:

  

具有相同名称和相同参数类型列表的成员函数声明以及具有相同名称,相同参数类型列表和相同模板参数列表的成员函数模板声明不能重载(如果有的话)他们,但不是全部,都有一个参考资格赛(8.3.5)。

答案 1 :(得分:3)

是的,您需要声明A changed() &&;。当实例是右值时,此重载将可用。

struct A
{ 
    void foo() &  { }
    void foo() && { }
};

int main()
{
    A x;
    x.foo();             // picks first overload
    std::move(x).foo();  // picks second overload
    A().foo();           // "typical" use case for second overload
}

所有编译器可能都不支持此新语言功能。