[英]Is there a right way to return a new object instance by reference in C++?
所以我写了一些代码,我有这样的事情:
class Box
{
private:
float x, y, w, h;
public:
//...
Rectangle & GetRect( void ) const
{
return Rectangle( x, y, w, h );
}
};
然后在一些代码中:
Rectangle rect = theBox.GetRect();
哪个在我的调试版本中有效,但在发行版中有“问题”通过引用返回Rectangle - 我基本上得到了一个未初始化的矩形。 Rectangle类有一个=运算符和一个复制构造函数。 在没有弄清楚为什么会破坏的情况下,我实际上更感兴趣的是通过引用返回(新)对象的正确方法, 以便将复制分配给变量。 我只是傻吗? 不应该这样做吗? 我知道我可以返回一个指针,然后取消引用,但我不愿意。 我的某些部分感觉像按值返回会导致对象的冗余复制 - 编译器是否会解决并优化它?
这似乎是一个微不足道的问题。 经过多年的C ++编码后,我感到尴尬,我不知道这一点,所以希望有人可以为我清除这一点。 :)
您不能返回对堆栈上的临时对象的引用。 你有三个选择:
请注意,当您按照下面的代码中的值返回时,编译器应优化分配以避免复制 - 即,它将通过优化create + assign + copy到create中来创建单个Rectangle(rect)。 这仅在从函数返回时创建新对象时有效。
Rectangle GetRect( void ) const
{
return Rectangle( x, y, w, h );
}
Rectangle rect = theBox.GetRect();
不,你不能这样做。 基本上,您在此示例中尝试执行的操作是返回对堆栈上的临时变量的引用。 返回引用时,它指向的变量将被销毁,因此引用无效。
按值返回对象(参见下面的示例)实际上可能比您想象的要便宜。 编译器通常会优化额外的副本。 这称为返回值优化 。
Rectangle GetRect( void ) const
{
return Rectangle( x, y, w, h );
}
有没有一种正确的方法通过C ++引用返回一个新的对象实例?
不,不是参考。 有两种方法可以创建新对象:
在堆栈上:
Rectangle makeRect()
{
return Rectangle(x, y, w, h);
}
Rectangle r = makeRect(); // return by value
在堆上:
Rectangle * makeRect()
{
return new Rectangle(x, y, w, y);
}
Rectangle * r = makeRect(); // returned a pointer, don't forget to delete it later
为什么不这样的?
class Box
{
private:
Rectangle mRectangle;
public:
Box(float x, float y, float w, float h) :
mRectangle(x, y, w, h) // Forgive me for making assumptions
// about the inner workings of your
// code here.
{
}
const Rectangle & GetRect() const
{
return mRectangle;
}
};
Rectangle rect = theBox.GetRect();
“任务”现在应该有效。 (从技术上讲,这不是一个赋值运算符,而是一个被调用的复制构造函数。)
希望能帮到你
Box
类内部的引用(具有Rectangle
成员。建议返回const
引用)。 Rectangle
。 注意使用成语return SomeClass(a,b,c);
可能会在合适的编译器上触发返回值优化(RVO) 。 检查std::complex
实现以获取详细信息。
你可能会对临时生命的概念感到困惑。 考虑:
void f1( const A & a ) {
}
A f2() {
return A;
}
f1( f2() );
这是好的代码,标准说f2创建的无名临时必须挂起足够长的时间才能在f1中使用。
但是,你的情况有所不同。 函数返回的东西是引用,因此无名临时也是引用。 该引用必须挂起足够长的时间才能有用,但它引用的内容不需要。
这是不可能的。 引用是指针的另一种形式,实际上您返回的对象的地址将被销毁(析构函数被调用),甚至可能在调用者接收控件时被覆盖。
你也可以
如果矩形按位看起来像Box,即包含四个浮点数(但有不同的成员函数),你可以使用reinterpret_cast ,虽然我根本不会推荐它:
const Rectangle & GetRect( void ) const
{
assert(sizeof(Rectangle) == sizeof(Box));
return reinterpret_cast <Rectangle> (*this);
}
我们可以使用auto_ptr,如果我们想使用新的和安全的内存泄漏
class Box {
private: float x, y, w, h;
public:
//...
std::auto_ptr<Rectangle> GetRect( void ) const
{
return std::auto_ptr<Rectangle> ( new Rectangle( x, y, w, h ));
}
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.