所以我正在编写一些代码,我有这样的东西:
class Box
{
private:
float x, y, w, h;
public:
//...
Rectangle & GetRect( void ) const
{
return Rectangle( x, y, w, h );
}
};
然后在一些代码中:
Rectangle rect = theBox.GetRect();
这在我的调试版本中有效,但在发布中存在通过引用返回该矩形的“问题” - 我基本上得到了一个未初始化的矩形。 Rectangle 类有一个 = 运算符和一个复制构造函数。 在不了解为什么会发生这种情况的情况下,我实际上更感兴趣的是通过引用返回(新)对象的正确方法为了分配复制到变量。我只是傻吗? 不应该这样做吗? 我知道我可以返回一个指针,然后在赋值时取消引用,但我宁愿不这样做。 我的某些部分感觉按值返回会导致对象的冗余复制——编译器是否能找出并优化它?
这似乎是一个微不足道的问题。 经过多年的 C++ 编码,我不知道这一点,我感到几乎尴尬,所以希望有人能为我解决这个问题。 :)
So I was writing some code, and I had something like this:
class Box
{
private:
float x, y, w, h;
public:
//...
Rectangle & GetRect( void ) const
{
return Rectangle( x, y, w, h );
}
};
Then later in some code:
Rectangle rect = theBox.GetRect();
Which worked in my debug build, but in release there were "issues" returning that Rectangle by reference -- I basically got an uninitialized rectangle. The Rectangle class has an = operator and a copy constructor. Without getting into why this broke, I'm actually more interested in the correct way to return a (new) object by reference for the purpose of assigning copying to a variable. Am I just being silly? Should it not be done? I know I can return a pointer and then dereference on assignment, but I'd rather not. Some part of me feels like returning by value would result in redundant copying of the object -- does the compiler figure that out and optimize it?
It seems like a trivial question. I feel almost embarrassed I don't know this after many years of C++ coding so hopefully someone can clear this up for me. :)
发布评论
评论(9)
您无法返回对堆栈上临时对象的引用。 您有三个选择:
请注意,当您按下面的代码中的值返回时,编译器应该优化分配以避免复制 - 即它只会创建一个矩形(矩形)将创建+分配+复制优化为创建。 仅当您从函数返回时创建新对象时,这才有效。
You can't return a reference to a temporary object on the stack. You have three options:
Note that when you return by value as in the code below, the compiler should optimize the assignment to avoid the copy - i.e. it will just create a single Rectangle (rect) by optimizing the create+assign+copy into a create. This only works when you create the new object when returning from the function.
不,你不能这样做。 本质上,您在此示例中尝试执行的操作是返回对堆栈上临时变量的引用。 当返回引用时,它指向的变量将被销毁,因此引用无效。
No you cannot do this. Essentially what you're trying to do in this sample is return a reference to a temporary variable on the stack. By the time the reference is returned, the variable it's pointing to will be destroyed and hence the reference is invalid.
按值返回对象(参见下面的示例)实际上可能比您想象的要便宜。 编译器通常会优化掉额外的副本。 这称为返回值优化。
Returning an object by value (see example below) may actually be less expensive than you think. The compiler often optimizes out the extra copy. This is called the return value optimization.
不,不是参考。 创建新对象有两种方法:
在堆栈上:
在堆上:
为什么不这样做呢?
“作业”现在应该可以工作了。 (从技术上讲,这不是赋值运算符,而是被调用的复制构造函数。)
希望有所帮助
No, not by reference. There are two ways to create a new object:
On the stack:
On the heap:
Why not something like this?
The 'assignment' should work now. (Technically this is not an assignment operator, but a copy constructor being invoked.)
Hoping to help
您可能对临时生命周期的概念感到困惑。 考虑一下:
这是正常的代码,并且标准规定 f2 创建的无名临时文件必须挂起足够长的时间才能在 f1 中使用。
但是,您的情况有些不同。 你的函数返回的是一个引用,因此无名临时也是一个引用。 该引用必须保留足够长的时间才能有用,但它所引用的内容则不需要。
You may be getting confused by the concept of the lifetime of a temporary. Consider:
This is OK code, and the standard says that the nameless temporary that f2 creates must hang round long enough to be useable in f1.
However, your case is somewhat different. The thing your function returns is a reference, and therefore the nameless temporary is also a reference. That reference must hang round long enough to be useful, but the thing it refers to need not.
这不可能。 引用是指针的另一种形式,实际上,您返回一个对象的地址,该对象将被销毁(调用析构函数),甚至可能在调用者收到控制权时被覆盖。
您可以
This is not possible. A reference is another form of a pointer and you in fact return an address of an object that will have been destroyed (destructor called ) and possibly even overwritten by the time the caller receives control.
You can either
Box
类内部的引用(有一个Rectangle
成员。建议返回const
引用)。矩形
。 请注意,使用习惯用法return SomeClass(a,b,c);
可能会触发 在不错的编译器上进行返回值优化 (RVO)。检查您的
std::complex
实现以了解详细信息。Box
class (have aRectangle
member. Returning aconst
reference is advised).Rectangle
. Note that using the idiomreturn SomeClass(a,b,c);
will probably trigger a return value optimization (RVO) on decent compiler.Check your
std::complex
implementation for details.如果矩形按位看起来像 Box ie 由四个浮点数组成(但有不同的成员函数),则可以使用reinterpret_cast,尽管我根本不推荐它:
If the rectangle bitwise looks like the Box i.e consists of four floats (but got different member functions) you could use a reinterpret_cast, although I would not at all recommend it:
如果我们想使用 new 并且安全地避免内存泄漏,我们可以使用 auto_ptr
we can use auto_ptr, if we want to use new and safe from Memory Leak