C++ 在C+;中是否有通过引用返回新对象实例的正确方法+;?
所以我写了一些代码,我有这样的想法:C++ 在C+;中是否有通过引用返回新对象实例的正确方法+;?,c++,object,reference,return,variable-assignment,C++,Object,Reference,Return,Variable Assignment,所以我写了一些代码,我有这样的想法: class Box { private: float x, y, w, h; public: //... Rectangle & GetRect( void ) const { return Rectangle( x, y, w, h ); } }; 然后在后面的一些代码中: Rectangle rect = theBox.GetRect(); 这在我的调试构建中起作用,但
class Box
{
private:
float x, y, w, h;
public:
//...
Rectangle & GetRect( void ) const
{
return Rectangle( x, y, w, h );
}
};
然后在后面的一些代码中:
Rectangle rect = theBox.GetRect();
这在我的调试构建中起作用,但在发行版中,通过引用返回该矩形存在“问题”——我基本上得到了一个未初始化的矩形。矩形类有一个=运算符和一个复制构造函数。不必解释为什么会出现这种情况,实际上我更感兴趣的是通过引用返回(新)对象的正确方法,以便将复制赋值给变量。我只是在傻吗?不应该这样做吗?我知道我可以返回一个指针,然后在赋值时取消引用,但我不愿意。我的某些部分感觉按值返回会导致对象的冗余复制——编译器是否能解决这一问题并对其进行优化
这似乎是个微不足道的问题。我感到很尴尬,我不知道这经过多年的C++编码,所以希望有人能为我澄清这一点。p> 不,你不能这样做。基本上,在这个示例中,您要做的是返回对堆栈上临时变量的引用。当引用返回时,它指向的变量将被销毁,因此引用无效 不能返回对堆栈上临时对象的引用。您有三种选择:
Rectangle GetRect( void ) const
{
return Rectangle( x, y, w, h );
}
Rectangle rect = theBox.GetRect();
- 返回对
类内部的引用(使用框
成员。建议返回矩形
引用)常量
- 或者只返回一个
。注意,使用习惯用法矩形
可能会触发一个新的编译器返回SomeClass(a,b,c)
查看您的
std::complex
实现以了解详细信息。您可能会被临时用户生命周期的概念弄糊涂。考虑:
void f1( const A & a ) {
}
A f2() {
return A;
}
f1( f2() );
这是OK代码,标准规定f2创建的无名临时文件必须挂起足够长的时间才能在f1中使用
然而,你的情况有所不同。函数返回的东西是一个引用,因此无名的临时对象也是一个引用。该引用必须挂起足够长的时间才有用,但它所指的东西不需要。这是不可能的。引用是指针的另一种形式,实际上,您返回的对象的地址将被销毁(调用析构函数),甚至可能在调用方接收到控制时被覆盖 你也可以
- 调用new并返回指向堆分配对象的指针(也许您应该考虑智能指针),或者
- 按值返回或
- 通过引用将对象传递到函数中,使其充满
如果矩形按位看起来像长方体,即由四个浮点数组成(但有不同的成员函数),则可以使用reinterpret_cast,但我不建议这样做:
const Rectangle & GetRect( void ) const
{
assert(sizeof(Rectangle) == sizeof(Box));
return reinterpret_cast <Rectangle> (*this);
}
const矩形和GetRect(void)const
{
断言(sizeof(矩形)==sizeof(长方体));
返回重新解释的铸件(*本);
}
如果我们想使用新的、安全的内存泄漏,我们可以使用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 ));
}
};
类框{
专用:浮动x、y、w、h;
公众:
//...
标准::自动ptr GetRect(无效)常量
{
返回std::auto_ptr(新矩形(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();
“任务”现在应该可以工作了。(从技术上讲,这不是赋值运算符,而是正在调用的复制构造函数。)
希望对您有所帮助那么您是说如果它是const-rectang&GetRect(…),那么它是正确的吗?问题不在于constness,而在于您有引用的东西是在堆栈上创建的。@pbhogan,不。我不应该在我的答案中添加const单词。那是我的错误。您只需在此处按值返回该值。请注意,代码中没有赋值。选项3:按引用返回您作为参数收到的内容。这在重写运算符时特别有用。在这个答案中,指针的示例会很好,比如矩形*GetRect(void)const{return new Rectangle(x,y,w,h)}矩形*rect=theBox.GetRect();稍后删除rect;你当然是对的。我在动态语言上花了太多时间——我开始期望临时语言的生命周期遵循引用。我的选项总结得很好,谢谢。我已经尽可能地实现了您的最后一个选项,但是这里的示例有点过于简单。Box实际上是更复杂的东西,GetRect返回一个计算过的矩形。不管怎样,你的第一个选择就是我应该做的。。。我只是想比编译器更聪明,我猜:p
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();