C++0x:当一个临时对象等于另一个临时对象时
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
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;
}
In this example, f()
and g()
respectively return a temporary object, so f()=g()
results in an expression of temporary object equal to temporary object. I would have expected that the answer is 14 if the value is correctly copied. However, it is NOT calling the copy assignment, BUT calling the move assignment! As a result, the answer is not 14.
This makes me really confused. Although the returning objects from f()
and g()
are temporary, they are sharing some information with some other objects. It implies the temporary objects might be doing some works shortly for the shared information. So I am supposed that semantically calling copy assignment would be the correct behaviors.
ps. My compiler is g++4.7 20110430
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您正在创建一个具有指向同一位置的指针的实例。使用
F::operator()
创建的实例不共享指针本身。f()=g()
相当于 f().operator=(g()) 并且g()
创建一个临时实例,因此调用是正确的移动作业。问题是在执行
f()=g()
之后,f
有一个悬空指针。f()
创建一个临时实例,它删除了移动赋值运算符中的指针,但f
本身仍然有一个指向删除位置的指针。我不确定你对这些复杂的代码做了什么,但你最好用
std::shared_ptr
或其他东西重写代码。ps 您不需要
std::move
返回实例。如果您没有关闭这些功能,您的编译器具有 RVO 功能。You are creating an instance which has a pointer pointing the same location. The instance created with
F::operator()
does not share the pointer itself.f()=g()
is equivalent to f().operator=(g()) andg()
creates a temporary instance, so it is correct to call move assignment.The problem is that
f
has a dangling pointer after the execution off()=g()
.f()
creates an temporary instance, it deletes the pointer in the move assignment operator, butf
itself still has a pointer which points the deleted location.I'm not sure what you're doing with those complicated code but you'd better rewrite the code with
std::shared_ptr
or something.p.s. You don't need
std::move
in returning an instance. Your compiler has RVO features if you didn't turn these off.您的
operator()
返回一个值,而不是引用或指针。因此,它返回一个临时值。临时变量隐式绑定到 &&优先(他们是唯一这样做的类型)。因此,如果有一个移动赋值运算符供他们使用,他们会更喜欢使用它。您的问题是,当您在
operator()
函数中执行此操作时,您停止了做合理的事情:采用指针的
F
构造函数使用指针值本身,有效地采用指针。此时,您现在有两个F
实例指向相同的数据。如果这是您想要合理的事情,那么您不能让移动赋值运算符删除指针。您需要协调这样一个事实:您可以有两个指向同一事物的
F
实例。两者需要共享指针的所有权。那么...你打算怎么做呢?我建议完全摆脱这个构造函数。它只会给你带来更多的问题。我还建议使用 std::unique_ptrdata; 而不是裸指针。这样,您就不必编写移动构造函数/赋值运算符(尽管您确实需要复制构造函数/赋值运算符)。
Your
operator()
returns a value, rather than a reference or pointer. Therefore, it returns a temporary. Temporaries implicitly bind to && preferentially (they are the only types to do so). Therefore, if there is a move assignment operator for them to use, they will prefer to use it.Your problem is that you stopped doing reasonable things when you did this in your
operator()
function:The constructor of
F
that takes a pointer uses the pointer value itself, effectively adopting the pointer. At that moment, you now have twoF
instances that point to the same data.If that's something you want to be reasonable, then you cannot have your move assignment operator delete the pointer. You need to reconcile the fact that you can have two
F
instances that point to the same thing. The two need to share ownership of the pointer. So... how do you plan to do that?I would suggest getting rid of this constructor altogether. It will only create more problems for you. I would also suggest using a
std::unique_ptr<int> data;
instead of a naked pointer. That way, you don't have to write a move constructor/assignment operator (though you do need a copy constructor/assignment operator).