如何 return 引用在方法内创建的对象
How to return references to object created inside a method
我正在推理 return 对在方法内创建的对象的引用的最佳方法,如以下情况:
class A{
public:
A(){}
~A(){}
};
class Foo{
public:
Foo(){}
~Foo(){}
A& create(int random_arg){
// create object A and return its reference
}
};
void other_method(){
Foo f;
A a = f.create();
// do stuff with a
{
我考虑了三种可能的解决方案:
创建原始指针和 return 引用,但这很糟糕,因为不能保证对象将被正确删除:
A& create(int random_arg){
A* a = new A();
return *a;
}
按值创建 shared_ptr 和 return shared_ptr。这样 shared_ptr 将负责对象删除:
shared_ptr<A> create(int random_arg){
boost::shared_ptr<A> a_ptr(new A());
return a_ptr;
}
创建一个 shared_ptr 和 return 一个引用:
A& create(int random_arg){
boost::shared_ptr<A> a_ptr(new A());
return *a_ptr;
}
第二个方案好像用的最多,但是这样我就得在应用中铺shared_ptr而且我更希望有参考,或者更好的const
参考。
您认为处理这种情况的最佳方法是什么?还有其他我没有考虑过的可能性吗?
不要这样做。您很可能有一个 悬空引用 .
只是 return A
的实例值。
编译器很可能会删除隐含的对象副本。但是您可以保证不会通过为A
.
编写移动构造函数来创建对象副本。
之所以 return 将指针或引用指向局部变量是一个坏主意,是因为它们通常在堆栈上,这意味着当堆栈再次到达该深度时,数据将被覆盖和损坏.
新手经常犯这样的错误,因为它经常碰巧是靠运气而让我放心的,即当你在调用任何其他函数破坏堆栈帧之前直接使用 returned 指针时上一个的。
按值返回可能适用于许多情况,编译器可以自由优化return。但即使没有优化,它也可能不是什么大问题,例如在 Qt 中,所有容器和许多其他 类 都隐式共享资源,因此 return 复制并不会真正复制所有数据,只是对象的 shell,通常是指向实际数据的单个指针。 C++ 中也有移动语义,这在这方面有点相似 - 它将责任从本地转移到 returned 对象而不进行深层复制。
有两种主要情况下 return 不需要按值。
- 如果涉及不可避免的重物复制
- 如果它是一个带有 "identity" 的对象——它们的复制构造函数和赋值运算符被禁用,所以它们不能真正被 return 按值编辑
在这些情况下,您只需动态分配对象并 return 指向它的指针。无论您是手动管理它还是更喜欢使用智能指针 - 这取决于您的需要。
完成 Bathsheba 的回答:
只有一种情况下您可能想要执行类似的操作,即如果您要将实例返回给单例。在这种情况下,这样的实例将是一个静态对象:
A& getTheOnlyInstanceOfA()
{
static A onlyInstOfA;
return onlyInstOfA;
}
我正在推理 return 对在方法内创建的对象的引用的最佳方法,如以下情况:
class A{
public:
A(){}
~A(){}
};
class Foo{
public:
Foo(){}
~Foo(){}
A& create(int random_arg){
// create object A and return its reference
}
};
void other_method(){
Foo f;
A a = f.create();
// do stuff with a
{
我考虑了三种可能的解决方案:
创建原始指针和 return 引用,但这很糟糕,因为不能保证对象将被正确删除:
A& create(int random_arg){ A* a = new A(); return *a; }
按值创建 shared_ptr 和 return shared_ptr。这样 shared_ptr 将负责对象删除:
shared_ptr<A> create(int random_arg){ boost::shared_ptr<A> a_ptr(new A()); return a_ptr; }
创建一个 shared_ptr 和 return 一个引用:
A& create(int random_arg){ boost::shared_ptr<A> a_ptr(new A()); return *a_ptr; }
第二个方案好像用的最多,但是这样我就得在应用中铺shared_ptr而且我更希望有参考,或者更好的const
参考。
您认为处理这种情况的最佳方法是什么?还有其他我没有考虑过的可能性吗?
不要这样做。您很可能有一个 悬空引用 .
只是 return A
的实例值。
编译器很可能会删除隐含的对象副本。但是您可以保证不会通过为A
.
之所以 return 将指针或引用指向局部变量是一个坏主意,是因为它们通常在堆栈上,这意味着当堆栈再次到达该深度时,数据将被覆盖和损坏.
新手经常犯这样的错误,因为它经常碰巧是靠运气而让我放心的,即当你在调用任何其他函数破坏堆栈帧之前直接使用 returned 指针时上一个的。
按值返回可能适用于许多情况,编译器可以自由优化return。但即使没有优化,它也可能不是什么大问题,例如在 Qt 中,所有容器和许多其他 类 都隐式共享资源,因此 return 复制并不会真正复制所有数据,只是对象的 shell,通常是指向实际数据的单个指针。 C++ 中也有移动语义,这在这方面有点相似 - 它将责任从本地转移到 returned 对象而不进行深层复制。
有两种主要情况下 return 不需要按值。
- 如果涉及不可避免的重物复制
- 如果它是一个带有 "identity" 的对象——它们的复制构造函数和赋值运算符被禁用,所以它们不能真正被 return 按值编辑
在这些情况下,您只需动态分配对象并 return 指向它的指针。无论您是手动管理它还是更喜欢使用智能指针 - 这取决于您的需要。
完成 Bathsheba 的回答:
只有一种情况下您可能想要执行类似的操作,即如果您要将实例返回给单例。在这种情况下,这样的实例将是一个静态对象:
A& getTheOnlyInstanceOfA()
{
static A onlyInstOfA;
return onlyInstOfA;
}