【问题标题】:C++0x: when a temporary object equals another temporary objectC++0x:当一个临时对象等于另一个临时对象时
【发布时间】:2012-02-02 05:10:23
【问题描述】:
struct F
{
private:
    int* data;

public:
    F( int n ) 
    { 
        data = new int; 
        *data = n; 
    }

    F( int* p ) 
    { 
        data = p; 
    }

    F& operator=( const F& f ) 
    { 
        *data = *(f.get_data()); 
        return *this; 
    }

    F& operator=( F&& f ) 
    {
        delete data;
        data = f.data;
        f.data = nullptr;
        return *this;
    }

    F& operator=( int n ) { *data = n; return *this; }

    F operator()() 
    {
        F cpy_f( data );
        return std::move( cpy_f );
    }

    int* get_data() const { return data; }
};

int main()
{
    F f( 12 );
    F g( 14 );
    f() = g();
    cout << *(f.get_data()) << endl;
}

在本例中,f()g() 分别返回一个临时对象,因此f()=g() 导致临时对象等于临时对象 的表达式。如果正确复制了该值,我会期望答案是 14。然而,NOT调用copy assignmentBUT调用move assignment!结果,答案不是 14。

这让我很困惑。尽管从f()g() 返回的对象是临时的,但它们与其他一些对象共享一些信息。这意味着临时对象可能很快就会为共享信息做一些工作。所以我认为语义上调用复制分配将是正确的行为。

ps。我的编译器是g++4.7 20110430

【问题讨论】:

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


【解决方案1】:

您的operator() 返回一个值,而不是引用或指针。因此,它返回一个临时的。临时对象隐式优先绑定到 &&(它们是唯一这样做的类型)。因此,如果有一个移动赋值运算符供他们使用,他们会更喜欢使用它。

您的问题是,当您在 operator() 函数中执行此操作时,您停止做合理的事情:

F cpy_f( data );

接受指针的F 的构造函数使用指针值本身,有效地采用了指针。此时,您现在有 两个 F 实例,它们指向相同的数据。

如果您希望这是合理的,那么您不能让您的移动赋值运算符删除指针。您需要调和这样一个事实,即您可以拥有两个指向同一事物的 F 实例。两者需要共享指针的所有权。那么……你打算怎么做呢?

我建议完全摆脱这个构造函数。它只会给你制造更多的问题。我还建议使用std::unique_ptr&lt;int&gt; data; 而不是裸指针。这样,您就不必编写移动构造函数/赋值运算符(尽管您确实需要一个复制构造函数/赋值运算符)。

【讨论】:

    【解决方案2】:

    您正在创建一个实例,该实例有一个指向同一位置的指针。使用F::operator() 创建的实例共享指针本身。

    f()=g()等价于f().operator=(g()),g()创建了一个临时实例,所以调用move assignment是正确的。

    问题是ff()=g()执行后有一个悬空指针。 f() 创建了一个临时实例,它删除了移动赋值运算符中的指针,但 f 本身仍然有一个指向已删除位置的指针。

    我不确定你在用那些复杂的代码做什么,但你最好用std::shared_ptr或其他东西重写代码。

    附言返回实例时不需要std::move。如果您没有关闭这些功能,那么您的编译器就有 RVO 功能。

    【讨论】:

      猜你喜欢
      • 2011-02-14
      • 1970-01-01
      • 1970-01-01
      • 2012-01-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多