2012-03-26 89 views
2

这些有什么区别?功能类型之间的区别

MyType myFunction(); 

MyType t = myFunction(); 

MyType &myFunction(); 

MyType t = myFunction(); 

const MyType &myFunction(); 

MyType t = myFunction(); 

这是怎么回事幕后?

回答

3

在这三种情况下,第二行是常见的:

MyType t = myFunction(); 

这条线得到调用myFunction的结果,并使用它来拷贝构造MyType称为t了新的元素。

现在就分歧。在第一种情况下,您按值返回,这意味着(语义上),编译器将创建myFunctionreturn语句中的对象的副本,然后将该副本用作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[](它们通常不会复制值,但会返回对存储数据的引用)。

但事实上,函数通常不返回静态生命的对象,而是返回本地。

+0

除了Meyers单例(由于各种原因,它不享受通用粘连),您可能会在'std :: vector'和'std :: map'中使用'[]'运算符等网站功能。它们可能是更常用的返回值引用的示例。 – 2012-03-26 12:37:32

+0

@JamesKanze:对,应该返回引用的类中有许多*访问器*。我试图限制对免费函数的回应,因为这似乎是问题的情况。将更新答案以包含该特定示例。谢谢。 – 2012-03-26 13:12:05

1

我假设这些都是免费的功能。

MyType myFunction(); 
MyType t = myFunction(); 

由值返回MyType对象。理论上,myFunction内部创建的对象在返回时被复制。实际上,RVO很可能会发生。

MyType &myFunction(); 
MyType t = myFunction(); 

通过参考返回。这很可能是未定义的行为,因为通过引用返回本地对象是非法的。但是,如果myFunctions是成员函数,则可以返回该类的成员MyType,只要实例超过t,就可以。

对于第二个代码片段,你应该得到一个警告 - “通过引用返回局部变量”或类似的东西。

+0

@OliCharlesworth是的,对不起。我立即纠正它。 – 2012-03-26 11:28:52

+0

“通过引用返回本地对象是非法的”...所以我应该如何返回在函数内创建的对象? – Cheetah 2012-03-26 11:29:46

+0

@按价值发展 - 就像第一个片段一样。 – 2012-03-26 11:30:12

-1

我猜你想要做的是一样的东西:

MyType *myFuntion() 
{ 
    MyType *t = new MyType; 
    // do something with t 
    return t; 
} 

// ... somewhere else ... 
MyType *t = myFunction(); 

即构造一个函数内一个新的对象,并返回一个指向它。别忘了打电话

delete t; 

以后某个地方!

0

大多数答案都是正确的,除了一个小的细节。

const MyType& t = myFunction(); 

看起来,如果myFunction()返回一个临时变量,这将是未定义的行为,但事实上并非如此。这不是UB,事实上,const引用将临时的生命周期扩展到const引用的生命周期。事实上,这是编译器优化最具潜力的版本,并且还提供了一个重要的教训,即在可能的情况下应始终将返回值返回到const引用。

+0

我不确定你在说什么。如果'myFunction()'返回一个值,那么它是一个临时的。总是。尽管临时(或C++ 03中的副本)的生命周期可能会延长,但绝对没有理由不在这里使用MyType t = myFunction()。如果'myFunction()'返回一个引用,那么它是未定义的行为,不管你如何处理返回值。 – 2012-03-26 12:40:55

+0

事后看来,我发现我是个傻瓜,因为我错过了函数sig。但基本上如果'MyType myFunction();'然后'const MyType&t = myFunction();'是有效和首选的。'MyType t = myFunction();'带有上面的签名更可能做一个经常不必要的临时(没有进入RVO和NRVO的细节)。 – Ylisar 2012-03-26 12:48:16

+1

或多或少。如果'myFunction()'按值返回,没有意义不使用它来初始化一个值;使局部变量成为参考类型只是额外的噪音。如果'myFunction()'返回一个引用,允许对象(其他地方存在)的多态性或(如果非const)修改,那么使用本地引用很容易,以避免每次调用该函数访问该对象。 – 2012-03-26 12:53:20

相关问题