博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
More Effective C++ 读书笔记六——临时对象
阅读量:6983 次
发布时间:2019-06-27

本文共 2732 字,大约阅读时间需要 9 分钟。

条款19:了解临时对象的来源

c++真正的所谓的临时对象是不可见的——不会再你的源代码中出现。此等匿名对象通常发生于两种情况:一是当隐式类型转换(implicit type conveersions)被施行起来以求函数调用能够成功;二是当函数返回对象的时候。

第一种情况的例子:

[cce lang=”cpp”]
#include <iostream>

class Int

{
public:
Int(int value) {
_value = value;
std::cout << "In constructor, count: " << ++count << std::endl;
}
~Int() {
std::cout << "In destructor\n";
}

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;
}
[/cce]
这个例子的运行结果是:
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 个实参时

条款21:利用重载(overload)避免隐式类型转换(implicit type conversions)

这里介绍的就是通过重载,避免编译器自动通过构造函数创建临时对象,但是重载太多后面的维护什么的成本也会上升,需要考虑这个的必要性。

每个“重载操作符”必须获得至少一个“用户定制类型”的自变量

条款20:协助完成返回值优化(RVO)

另一个容易产生临时对象的地方就是函数返回值。不过经过尝试,发现目前编译器(g++)可以把命名变量也通过返回值优化去除。

也就是说,这样写:
[cce lang=”cpp”]
#include <iostream>

class Int

{
public:
Int(int value) {
_value = value;
std::cout << "In constructor, count: " << ++count << " value: " << _value <<std::endl;
}
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;

}
[/cce]
和这样写:
[cce lang=”cpp”]
#include <iostream>

class Int

{
public:
Int(int value) {
_value = value;
std::cout << "In constructor, count: " << ++count << " value: " << _value <<std::endl;
}
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;

}
[/cce]
最终的执行结果都是一样的:
In constructor, count: 1 value: 1
In constructor, count: 2 value: 2
In constructor, count: 3 value: 3
没有因为前者在operator+中多了一个result对象而多一个临时变量。

转载自:https://coolex.info/blog/276.html

你可能感兴趣的文章
linux启动过程
查看>>
我的友情链接
查看>>
我的友情链接
查看>>
xmlUtil 解析 创建
查看>>
我的友情链接
查看>>
linux 命令(3)echo
查看>>
Nginx基础入门之nginx基础配置项介绍(2)
查看>>
一次详细全面的***报告
查看>>
c# 三种异步编程模型EAP(*)、 APM(*)和 TPL
查看>>
deepin-安装问题:unable to find a medium containing a live file
查看>>
用 Hasor 谈一谈MVC设计模式
查看>>
IE 条件注释
查看>>
Windows热键注册(反汇编方法 查看win32api 原理)
查看>>
UNREFERENCED_PARAMETER的作用
查看>>
PHP计算表达式-栈
查看>>
sysbench OLTP基准测试
查看>>
IBATIS中关于iterate"$"与"#"的应用
查看>>
centos -bash: vim: command not found
查看>>
为什么要将对象序列化
查看>>
新增网址/网页 截图api[增加安全防护本接口已停用]源码可下载
查看>>