Prefer pass-by-reference-to-const to pass-by-value
这个问题在在C++是非常常见的。传值和传引用巨大的差别在于你所使用的参数是其本身还是其副本。缺省情况下C++是以by value 传递的。其副本是对象本身的copy 构造函数自动调用的。有关对象自动调用的五个函数请看条款12.下面看一下例子吧 :
运行结果如图:
从结果我们可以看到 构造函数,析构函数都调用了,其实远不止这些,因为上述两个类都含有两个string,他们也相应的调用构造函数,就是说四次string构造动作,还有析构。
总计12次,也就是我们简单的一个调用,动用了这么多函数。很浪费资源。
下面我们用 pass-by-reference-to-const来。
修改代码为
运行的结果:
如图,程序只调用了构造函数。在这里注明书中说没有调用任何构造函数和析构函数,应该是调用了构造函数了吧。跪求高人解释
by-reference避免了对象切割,什么是对象切割,请看下边的例子。
运行的结果如图所示:
可以看出,我们想得到WindowWithScrollBars display() ,但是我们得到的是上述的。它调用 是window对象,而不是子类的。因为他是by value,WindowWithScrollBars的所有特化信息都会被切除,这就是对象切割。那么解决办法就是
pass-by-reference-to-const,
修改代码如下:
运行结果得到:
从中我们看到了通过pass-by-reference-to-const,得到了我们想要的结果。
解释一下:
(1)所谓的slicing问题,也就是如果你把子类的对象赋值给父类的对象,如果用reference和指针,当然是可以的,而且这也是virtual的实现必需品。但是,如果用pass-by-value,就会出现,传进去的总是父类的对象,在传递对象的时候出现了切割问题。
(2)如果窥视c++编译器的底层,你会发现,references往往以指针实现出来,因此pass-by-reference通常意味着这真正传递的是指针。因此如果你有个对象属于内置类型(如int),pass by reference或pass by reference to const时,选择pass by value并非没有道理。这个忠告也适用于STL的迭代器和函数对象,因为习惯上它们都被设计为pass by value。迭代器和函数对象的实践者有责任看看他们是否高效且不受切割问题的影响。
(3)内置类型都相当的小。因此有人认为,所有小类型的types都是pass by value的合格候选人,甚至他们是用户自定义的class亦然。这是个不可靠的推论。对象小并不就意味其copy构造函数不昂贵。许多对象,包括STL容器,内含的东西只比一个指针多一些,但复制这种东西对象却需要承担“复制那些指针的每一样东西”。那将非常昂贵。
即使小型对象拥有并不昂贵的copy构造函数,还是可能有效率上的争议。某些编译器对待“内置类型”和“用户自定义类型”的态度截然不同,总是两者有相同的底层表述。举个例子,某些编译器拒绝把只由一个double组成的对象放进缓存器内,却很乐意在一个正规基础上对光秃秃的double那么做。当这种事发生,你更应该以by reference方式传递此等对象,因为编译器当然会将指针(references的实现体)放进缓存器内,绝无问题。
小型的用户自定义类型并不必然成为pass by value优良候选人的另一个理由是,作为一个用户自定义类型,其大小容易有所改变。甚至当你改用另一个c++编译器都有可能改变type的大小。举个例子,某些标准程序库实现版本中的string类型比其他版本大七倍!
请记住:
▲ 尽量以pass-by-reference-to-const替换pass-by-value.前者通常比较高效,并可避免切割问题(slicing
problem).
▲ 以上规则并不适合与内置类型,以及STL的迭代器和函数对象.对它们而言,pass-by-value往往比较适合.
分享到:
相关推荐
1、为什么要宁以pass-by-reference-to-const 替换 pass-by-value 效率方面 缺省情况下,C++以by value 方式传递对象至(或来自)函数。 除非你另外指定,否则函数参数都是以实际实参的副本为初值,而调用段所获得的...
条款20:宁以pass-by-reference-to-const替换Pass-by-value 条款21:必须返回对象时,别妄想返回其reference 条款22: 将成员变量声明为private 条款23: 宁以non-member、non-friend替换member函数 条款24:若...
条款20:宁以pass-by-reference-to-const替换pass-by-value prefer pass-by-reference-to-const to pass-by-value. 条款21:必须返回对象时,别妄想返回其reference don't try to return a reference when you must ...
optional lite:C++17-like optional 的单文件头版本,C++98、C++11 和更高版本的可为空对象 内容std::optional、optional lite 和Boost.Optional 的比较报告与构建测试实施说明可选的其他实现注释和参考附录 示例...
徐彤老师耗时三年倾心制作,专业录制,通俗,细致的讲解了C++ 编程从入门到高级
徐彤老师耗时三年倾心制作,专业录制,通俗,细致的讲解了C++ 编程从入门到高级
13)..Added: "User" and "Session" columns to processes list, processes list is also sorted by session first 14)..Added: Support for showing current user processes only 15)..Added: Expanding environment...
const reportTo = require ( 'report-to' ) // ... app . use ( reportTo ( { groups : [ { group : "endpoint-1" , max_age : 10_886_400 , include_subdomains : true , endpoints : [ { url : ...
徐彤老师耗时三年倾心制作,专业录制,通俗,细致的讲解了C++ 编程从入 门到高级
徐彤老师耗时三年倾心制作,专业录制,通俗,细致的讲解了C++ 编程从入 门到高级
HTTP::Status::Const - 可插入的 HTTP 状态常量 版本 v0.2.3 概要 use HTTP::Status::Const; ... $response->status( $HTTP_NOT_FOUND ); ... my %handlers = ( $HTTP_OK => sub { ... }, $...
const modifiers from demangled C++ function names -w, --wrap wrap function names --skew=THEME_SKEW skew the colorization curve. Values variety to lower percentages. Value > 1.0 give less variety...
and C++14, but instead to their effective application. The information in the book is broken into guidelines called Items. Want to understand the various forms of type deduction? Or know when (and ...
1.2 条款02:尽量以const,enum,inline替换#define 这个条款或许可以改为“宁可用编译器替换预处理器”。 通常C++要求你对所使用的任何东西提供一个定义式,但如果它是个class专属常量 又是static且为整数类型...
c++ 的array源码分析和reverse-iterator和-Array-const-iterator类
EFFECTIVE C++ 条款03 尽量使用const 思维导图
想全面学习Webpack?试试它: 不错替代品,可以使webpack将HTML用作条目并处理多页。 安装 npm i web-webpack-plugin --save-dev const { WebPlugin , AutoWebPlugin } = require ( 'web-webpack-plugin' ) ; 特征 ...
.\XXXX.cpp(27): error 1720: (Info -- assignment operator for class 'Object' has non-const parameter) void * operator new(size_t size, int i=0) {return 0;} // ECPP Items 8,9,10 .\XXXX.cpp(31): error ...
␞{"d":"2014-09-22T21:58:35.270Z","value":6} ␞{"d":"2014-09-22T21:59:15.117Z","value":12} 其中“␞”是ASCII“记录分隔符”字符(U + 001E),而“”是ASCII“ LINE FEED”字符(U + 000A),也称为...
const data = [ { name : "Cheese" , value : "cheese-value" } , { name : "Cheese" , value : "cheese-value" , items : [ { name : "Spicy" , value : "spicy-value" } , { name : "Cheese" , ...