关于从函数返回一个对象我很困惑。例如:
class A
{
public:
~A(){}
};
A find()
{
...
A a;
return a;
}
它是通过引用还是通过值返回“a”?此外,“查找”首先删除“a”,然后先返回或返回,然后删除“a”?
A find()
{
...
A a;
return a;
}
按值返回。
从技术上讲,a
的副本被构建,a
被销毁并且副本被返回。我在C ++标准中找不到任何指定这些操作的特定顺序的东西,但有些逻辑暗示。显然你破坏后无法复制。
我怀疑这是未指定的,以允许C ++实现支持各种各样的calling conventions。
注意:这意味着返回的对象必须是可复制的。如果复制构造函数被删除或无法访问,则无法按值返回。
无法确定返回或破坏是否是第一个。这应该没关系,如果你正在设计一个程序,那么就要动摇你的头脑。
然而,在实践中,现代优化编译器将尽其所能避免在Return Value Optimization的全名下使用各种方法进行复制和销毁。
请注意,这是一种罕见的情况,允许As-If Rule被违反。通过跳过复制构造和破坏,可能不会发生一些副作用。
另请注意,即使消除了复制的需要,对象仍必须是可复制的。
A & find()
{
...
A a;
return a;
}
将返回一个参考,但这是一个非常糟糕的主意。 a
具有由函数确定范围的自动存储持续时间,并将在返回时销毁。这会给调用者留下一个dangling reference,这是对不再存在的变量的引用。
为了解决这个问题,
std::unique_ptr<A> find()
{
...
auto a = std::make_unique<A>();
return a;
}
但是你会发现,使用现代编译器,在大多数情况下,这并不比按值返回更好。
在您的函数中,您将返回一个值,而不是引用。
A find();
返回类型是A
。是值,a
的副本将返回。
为了返回引用,您应该按如下方式编写函数。
A& find();
返回类型A&
表示对A的引用。但是您的函数体应该相应地更改,以便返回有效的引用。
使用当前实现,您将在函数内创建对象a
。因此,当它超出范围时,在函数执行结束时会被删除。
你的问题“而且,确实”找到“删除”一个“首先,然后返回或先返回,然后删除”一个“?”
a
的副本将首先返回,然后a
将删除。
如果返回引用,将返回引用,然后将删除对象a
。这样您的返回引用无效。