这些有什么区别?功能类型之间的区别
MyType myFunction();
MyType t = myFunction();
和
MyType &myFunction();
MyType t = myFunction();
和
const MyType &myFunction();
MyType t = myFunction();
这是怎么回事幕后?
这些有什么区别?功能类型之间的区别
MyType myFunction();
MyType t = myFunction();
和
MyType &myFunction();
MyType t = myFunction();
和
const MyType &myFunction();
MyType t = myFunction();
这是怎么回事幕后?
在这三种情况下,第二行是常见的:
MyType t = myFunction();
这条线得到调用myFunction
的结果,并使用它来拷贝构造的MyType
称为t
了新的元素。
现在就分歧。在第一种情况下,您按值返回,这意味着(语义上),编译器将创建myFunction
中return
语句中的对象的副本,然后将该副本用作t
复制构造的源。编译器很可能会删除副本(至少是第二个)。
在另外两种情况下,函数返回引用到某个其他对象。如果对象是本地人,那么它是未定义的行为。两者之间的区别在于返回的引用是否可以用来修改引用的对象,这可能会影响使用的拷贝构造函数或者它可以被使用。请注意,您从中获取引用的对象必须超过函数调用,否则您将导致未定义的行为。
// an example where it matters:
typedef std::auto_ptr<int> MyType;
MyType t = myFunction();
因为std::auto_ptr
修改分配上右手边,前面的代码将仅在返回的引用是非const的工作。
陆points指出,返回参考很可能是未定义的行为,所以什么时候它不会?当从中获得参考的对象超过参考的使用时。这是Meyers单件的基本构建块:
// an example where returning a reference is correct
MyType & myFunction() {
static MyType instance; // Note static storage duration!
return instance;
}
或者返回对子对象的引用的任何普通存取器。一些常见的情况是容器中的operator[]
(它们通常不会复制值,但会返回对存储数据的引用)。
但事实上,函数通常不返回静态生命的对象,而是返回本地。
我假设这些都是免费的功能。
MyType myFunction();
MyType t = myFunction();
由值返回MyType
对象。理论上,myFunction
内部创建的对象在返回时被复制。实际上,RVO很可能会发生。
MyType &myFunction();
MyType t = myFunction();
通过参考返回。这很可能是未定义的行为,因为通过引用返回本地对象是非法的。但是,如果myFunctions
是成员函数,则可以返回该类的成员MyType
,只要实例超过t
,就可以。
对于第二个代码片段,你应该得到一个警告 - “通过引用返回局部变量”或类似的东西。
@OliCharlesworth是的,对不起。我立即纠正它。 – 2012-03-26 11:28:52
“通过引用返回本地对象是非法的”...所以我应该如何返回在函数内创建的对象? – Cheetah 2012-03-26 11:29:46
@按价值发展 - 就像第一个片段一样。 – 2012-03-26 11:30:12
我猜你想要做的是一样的东西:
MyType *myFuntion()
{
MyType *t = new MyType;
// do something with t
return t;
}
// ... somewhere else ...
MyType *t = myFunction();
即构造一个函数内一个新的对象,并返回一个指向它。别忘了打电话
delete t;
以后某个地方!
大多数答案都是正确的,除了一个小的细节。
const MyType& t = myFunction();
看起来,如果myFunction()返回一个临时变量,这将是未定义的行为,但事实上并非如此。这不是UB,事实上,const引用将临时的生命周期扩展到const引用的生命周期。事实上,这是编译器优化最具潜力的版本,并且还提供了一个重要的教训,即在可能的情况下应始终将返回值返回到const引用。
我不确定你在说什么。如果'myFunction()'返回一个值,那么它是一个临时的。总是。尽管临时(或C++ 03中的副本)的生命周期可能会延长,但绝对没有理由不在这里使用MyType t = myFunction()。如果'myFunction()'返回一个引用,那么它是未定义的行为,不管你如何处理返回值。 – 2012-03-26 12:40:55
事后看来,我发现我是个傻瓜,因为我错过了函数sig。但基本上如果'MyType myFunction();'然后'const MyType&t = myFunction();'是有效和首选的。'MyType t = myFunction();'带有上面的签名更可能做一个经常不必要的临时(没有进入RVO和NRVO的细节)。 – Ylisar 2012-03-26 12:48:16
或多或少。如果'myFunction()'按值返回,没有意义不使用它来初始化一个值;使局部变量成为参考类型只是额外的噪音。如果'myFunction()'返回一个引用,允许对象(其他地方存在)的多态性或(如果非const)修改,那么使用本地引用很容易,以避免每次调用该函数访问该对象。 – 2012-03-26 12:53:20
除了Meyers单例(由于各种原因,它不享受通用粘连),您可能会在'std :: vector'和'std :: map'中使用'[]'运算符等网站功能。它们可能是更常用的返回值引用的示例。 – 2012-03-26 12:37:32
@JamesKanze:对,应该返回引用的类中有许多*访问器*。我试图限制对免费函数的回应,因为这似乎是问题的情况。将更新答案以包含该特定示例。谢谢。 – 2012-03-26 13:12:05