了解临时对象的来源
c++真正的所谓的临时对象是不可见的——不会再你的源代码中出现。此等匿名对象通常发生于两种情况:一是当隐式类型转换(implicit type conveersions)被施行起来以求函数调用能够成功;二是当函数返回对象的时候。
第一种情况的例子:
代码如下 | 复制代码 |
#include class Int { public: Int(int value) { _value = value; std::cout << "In constructor, count: " << ++count << std::endl; } ~Int() { std::cout << "In destructorn"; } int _value; private: static int count; }; int Int::count = 0; void printInt(Int intValue) { std::cout << "int value is: " << intValue._value << std::endl; } int main() { printInt(10); return 0; } |
这个例子的运行结果是:
In constructor, count: 1
int value is: 10
In destructor
验证了编译器再发现没法调用printInt(int)的时候,会进行自动类型转换,通过Int的构造函数,将int隐式转换成Int(这个貌似之前也提到过了)。这个构造出来的就是所谓的临时对象,从输出的顺序看,这个对象在函数返回之后被析构。
只有当对象以by value(传值)方式传递,或是当对象被传递给一个reference-to -const参数时,这些转换才会发生。如果参数被传递给一个reference-to-non-const参数,并不会发生此类转换
也就是说,把上面的printInt入参改成Int&的时候,就无法调用成功。原因很简单了,这个临时对象,如果没修改,函数返回之后也被析构了,没法再次获取到,即使允许也是没意义的。改成Int&之后,编译器(g++)有这样的报错:
tmp.cpp: 在函数‘int main()’中:
tmp.cpp:27:13: 错误:用类型为‘int’的右值初始化类型为‘Int&’的非常量引用无效
tmp.cpp:21:6: 错误:在传递‘void printInt(Int&)’的第 1 个实参时
利用重载(overload)避免隐式类型转换(implicit type conversions)
这里介绍的就是通过重载,避免编译器自动通过构造函数创建临时对象,但是重载太多后面的维护什么的成本也会上升,需要考虑这个的必要性。
每个“重载操作符”必须获得至少一个“用户定制类型”的自变量
协助完成返回值优化(RVO)
另一个容易产生临时对象的地方就是函数返回值。不过经过尝试,发现目前编译器(g++)可以把命名变量也通过返回值优化去除。
也就是说,这样写:
代码如下 | 复制代码 |
#include class Int { public: Int(int value) { _value = value; std::cout << "In constructor, count: " << ++count << " value: " << _value < Int(const Int &rhs) { _value = rhs._value; std::cout << "In copy constructor, count: " << ++count << " value: " << _value << std::endl; } friend const Int operator+(const Int &lhs, const Int &rhs); private: int _value; static int count; }; int Int::count = 0; const Int operator+(const Int &lhs, const Int &rhs) { Int result(lhs._value + rhs._value); return result; } int main() { Int a(1); Int b(2); Int c = a + b; return 0; } |
和这样写:
代码如下 | 复制代码 |
#include class Int { public: Int(int value) { _value = value; std::cout << "In constructor, count: " << ++count << " value: " << _value < Int(const Int &rhs) { _value = rhs._value; std::cout << "In copy constructor, count: " << ++count << " value: " << _value << std::endl; } friend const Int operator+(const Int &lhs, const Int &rhs); private: int _value; static int count; }; int Int::count = 0; const Int operator+(const Int &lhs, const Int &rhs) { return Int(lhs._value + rhs._value); } int main() { Int a(1); Int b(2); Int c = a + b; return 0; } |
最终的执行结果都是一样的:
In constructor, count: 1 value: 1
In constructor, count: 2 value: 2
In constructor, count: 3 value: 3
没有因为前者在operator+中多了一个result对象而多一个临时变量。
茶杯头甜蜜终章dlc 官方手机版v1.0.0.3
下载火柴人传说暗影格斗内置菜单 最新版v3.0.1
下载荒野乱斗测试服 安卓版v61.10.3
下载荒野乱斗彩虹服 安卓版v61.10.3
下载寒霜启示录 安卓版v1.25.10
寒霜启示录是一款生存模拟游戏,不少玩家可能对于末日都有着自己
末日城堡免广告版 安卓最新版v0.7.1
末日城堡免广告版是一款非常好玩的模拟经营类游戏,内部可以不看
甜蜜人生模拟器 最新版v1.4.5
甜蜜人生模拟器是一款非常好玩的模拟恋爱手游,玩家在这里能够对
武器锻造师内置功能菜单 v10.4
武器锻造师内置菜单版是游戏的破解版本,在该版本中为玩家提供了
开放空间overfield 安卓版v1.0.5
开放空间Overfield是一款箱庭养成经营手游,让你在广阔