3

*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){
}
4

2 回答 2

4

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

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

但是,您不能用具有参考限定的版本来重载没有参考限定的版本。见 13.1 [over.load] 第 2 段,第三个项目符号:

同名同参数类型列表的成员函数声明,同名同参数类型列表的成员函数模板声明,同模板形参列表中的任何一个都不能重载,但是不是全部,有一个 ref-qualifier (8.3.5)。

于 2013-08-25T19:42:18.543 回答
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
}

所有编译器可能还不支持这种新的语言特性。

于 2013-08-25T19:39:44.787 回答