C++0x:当一个临时对象等于另一个临时对象时

C++0x: when a temporary object equals another temporary object

本文关键字:临时对象 另一个 一个 C++0x      更新时间:2023-10-16
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。但是,它不是调用复制赋值,而是调用移动赋值结果,答案不是14。

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

附言。我的编译器是 g++4.7 20110430

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

你的问题是,当你在operator()函数中这样做时,你停止了做合理的事情:

F cpy_f( data );

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

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

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

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

f()=g() 等效于 f((.operator=(g(((,并且g()创建一个临时实例,因此调用移动分配是正确的。

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

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

附言返回实例时不需要std::move。如果未关闭这些功能,则编译器具有 RVO 功能。

相关文章: