函数类型之间的差异
Difference between function types
它们之间有什么区别?
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
修改了赋值的右侧,所以只有当返回的引用是非常量时,前面的代码才会起作用。
Luchian指出,返回引用很可能是未定义的行为,那么什么时候不会呢?当从中获取引用的对象超过引用的使用寿命时。这是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
长就可以了。
对于第二个代码片段,您应该得到一个警告——"通过引用返回局部变量"或类似的内容。
除了一个小细节外,大多数答案都是正确的。
const MyType& t = myFunction();
看起来,如果myFunction()返回一个临时变量,这将是未定义的行为,但事实并非如此。这不是UB,事实上const引用将临时的生存期扩展到const引用的生存期。事实上,这是最有可能进行编译器优化的版本,也提供了一个重要的教训,即在可能的情况下,应该始终将返回值放入常量引用中。
我想你想做的是:
MyType *myFuntion()
{
MyType *t = new MyType;
// do something with t
return t;
}
// ... somewhere else ...
MyType *t = myFunction();
即在函数中构造一个新对象并返回一个指向它的指针。不要忘记调用
delete t;
稍后的某个地方!
- C++LinkedList问题.数据类型之间存在冲突?没有匹配的构造函数
- 在类型和包装器之间reinterpret_cast是否安全<Type>?
- 为什么 c++(g++) 不允许模板返回类型和函数名称之间有空格?
- C ++中无符号位长度类型之间的隐式转换,即uint8_t,uint16_t
- 为什么不同类型层次结构的指针之间的dynamic_cast定义得很好?
- 非类类型表达式的静态类型与动态类型之间的差异
- 如何使用静态多态性在 int 和指针类型之间进行转换?
- 指向 POD 类型的指针之间的静态转换与重新解释转换
- 在 Rcpp 中的字符串类型之间转换时出错
- 如何在不同类型的值之间进行选择以传递给多态函数?
- 如何声明不同类型的模板化类之间的转换
- 在硬件SIMD矢量指针和相应类型之间进行"interpret_cast"是一种未定义的行为吗
- "+=" 操作在类型之间不起作用 std::复杂<double>和__complex__双精度
- 无符号长整型和无符号 int 之间有什么区别,这 2 种类型应该如何在 c# 中封送?
- 不同c++编译器之间的自动类型推导不匹配
- 类型测试对象的动态数组的这两个声明之间的区别?
- 使用模板在size_t和int之间进行隐式类型转换
- 为什么C++中的表达式类型在不同版本之间会发生变化
- 您可以在具有相同表示形式的类型之间reinterpret_cast吗?
- C和c++之间类型转换的差异