【问题标题】:Move semantic and temporary implicit this移动语义和临时隐式 this
【发布时间】:2013-08-25 19:35:06
【问题描述】:

当对象 *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){
}

【问题讨论】:

    标签: c++ optimization methods move-semantics


    【解决方案1】:

    您可以在*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)。

    【讨论】:

    • 等等,左值版本不只是使用熟悉的语法(没有&amp;)?
    • 哦,我在 13.3.1 中看到两者都是可能的。为什么你会选择不使用 ref-qualifier 而不是 &amp; ref-qualifier,因为两者都绑定左值?
    • @BenVoigt:当你想用右值版本重载它时不是。我正在将子句添加到响应中。
    • 啊,这很好解释。谢谢。
    • @Walter:我正在使用 gcc (4.9.0 20130811 (experimental)) 和 clang (version 3.4 (trunk 182411)),它们都包含这个特性。我没有英特尔的编译器。 clang-3.3 似乎也实现了这个功能。
    【解决方案2】:

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

    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
    }
    

    可能并非所有编译器都支持这一新语言功能。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-04-11
      • 2017-04-20
      • 2016-02-04
      • 2020-08-20
      • 2012-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多