这些之间有什么区别?
MyType myFunction();
MyType t = myFunction();
和
MyType &myFunction();
MyType t = myFunction();
和
const MyType &myFunction();
MyType t = myFunction();
幕后发生了什么?
答案 0 :(得分:3)
在这三种情况下,第二行很常见:
MyType t = myFunction();
该行获得调用myFunction
的结果,并将其用于 copy-construct MyType
的新元素t
。
现在就差异了。在第一种情况下,您按值返回,这意味着(语义上),编译器将创建return
语句中myFunction
语句中的对象的副本,然后使用该副本作为源用于t
的复制构造。编译器很可能会删除副本(至少是第二个)。
在另外两种情况下,函数将引用返回给其他对象。如果对象是本地对象,那么它是未定义的行为。两者之间的区别在于返回的引用是否可用于修改引用的对象,这可能会影响使用的复制构造函数或是否可以使用它。请注意,从中获取引用的对象必须比函数调用更长,否则将导致未定义的行为。
// an example where it matters:
typedef std::auto_ptr<int> MyType;
MyType t = myFunction();
因为std::auto_ptr
在赋值时修改了右侧,所以前面的代码只有在返回的引用是非const时才有效。
Luchian指出,返回引用很可能是未定义的行为,所以何时不会?当获得引用的对象超过引用的使用时间。这是迈耶斯单身人士的基本组成部分:
// an example where returning a reference is correct
MyType & myFunction() {
static MyType instance; // Note static storage duration!
return instance;
}
或任何返回对子对象的引用的普通访问器。容器中的一些常见情况是operator[]
(它们通常不复制值,但返回对存储数据的引用)。
但确实,通常情况下,函数不会返回静态生存的对象,而是返回本地对象。
答案 1 :(得分:1)
我假设这些是免费功能。
MyType myFunction();
MyType t = myFunction();
按值返回MyType
个对象。从理论上讲,myFunction
中创建的对象在返回时被复制。实际上,RVO最有可能发生。
MyType &myFunction();
MyType t = myFunction();
以引用方式返回。这很可能是未定义的行为,因为通过引用返回本地对象是非法的。但是,如果myFunctions
是成员函数,则可以返回属于该类成员的MyType
,只要该实例超过t
,就可以了。
对于第二个代码段,您应该收到警告 - “通过引用返回本地变量”或类似的内容。
答案 2 :(得分:0)
除了一个小细节外,大多数答案都是正确的。
const MyType& t = myFunction();
似乎如果myFunction()返回一个临时变量,这将是未定义的行为,但实际上并非如此。这不是UB,实际上const引用将临时的生命周期延长到const引用的生命周期。事实上,这是一个最有可能进行编译器优化的版本,并且还提供了一个重要的教训,即在可能的情况下应始终将返回值转换为const引用。
答案 3 :(得分:-1)
我想你想要做的是:
MyType *myFuntion()
{
MyType *t = new MyType;
// do something with t
return t;
}
// ... somewhere else ...
MyType *t = myFunction();
即。在函数内部构造一个新对象并返回一个指向它的指针。别忘了打电话
delete t;
某个地方以后!