【讨论】方法返回类型为const引用型你们在公司做项目时会用到吗?

hunterzone 2014-04-24 09:01:51
背景:我所在的项目组是平台开发组,我在我定义的类里,返回类里的属性变量(数据类型为类类型)我是采用的const引用型,我的考虑是少一次拷贝,提高效率,代码例如下:

class A
{};

class B
{
const A& getA() const { return m_a; }
private:
A m_a;
}

昨天组长看了我的代码之后把我大骂了一顿,说我const和引用根本不会用,而且乱用,我心里那个委屈呀~~~~~
今天找我们组的架构师聊到这个问题他也说我用的不对,说从没见过这种用法,还说我是学院派,说看到书上这么用好我就拿来用,我彻底郁闷了。
在此想请问各位大牛,你们平时在公司做项目的使用返回类型会用到const引用型吗?这种用法常见吗?
...全文
1960 100 打赏 收藏 转发到动态 举报
写回复
用AI写文章
100 条回复
切换为时间正序
请发表友善的回复…
发表回复
苦逼码农 2014-06-04
  • 打赏
  • 举报
回复
引用 5 楼 mujiok2003 的回复:
除非这个方法是出现在性能焦点处,否则没有必要返回引用,直接返回拷贝就好。 引用可以省去拷贝的开销,但是也有生存期管理方面的隐忧。
高手帮忙解答个boost的问题, http://bbs.csdn.net/topics/390775392 多谢
饭来张 2014-06-03
  • 打赏
  • 举报
回复
[/quote] 又是一个觉得c++比c好的sb。优秀的程序员是不分语言的。最看不起那些语言之争的人。[/quote] 又是个二货C半吊子。 先艹几年代码再艹几年standization跟PLT再在这里叫。 最看不起这种说啥啥不懂一个劲ZB还YY别人需求的渣。哦,还有扯什么“语言就是工具”“学C之前一定要汇编”的战五渣以及易经厨。 C的SB地方没C艹的多,但是显然程度上没得比。再优秀的程序员也抗不过一群二B用弱智解决方案绑架需求。连语言好坏都不敢直视的只会纸上谈兵的就别JJYY浪费氧气了。 [/quote] 已经举报,对这种极其没素质的人大家要积极举报。免得污染了论坛。 现在it界这种喷粪的人咋这么多,特别是csdn这种地方,论坛再不净化下,都没法带了。
FrankHB1989 2014-05-19
  • 打赏
  • 举报
回复
引用 96 楼 book_withc 的回复:
[quote=引用 91 楼 FrankHB1989 的回复:] [quote=引用 89 楼 book_withc 的回复:] c,c++写出的任何代码都不是100%完美的。总有其优点和缺点。 只要判断下,选择一个优点最多的方案就好了。 比如,总是不建议从函数内部分配内存,然后返回给外面指针。这样做后,分配的内存由谁释放是个无法控制的问题。 但是,还是有很多情况可以使用这种方法。 这样做不好的原因是,内部分配,外部释放,担心外部使用的人会忘记释放。 只要能够保证外面能够正确的释放就可以。 如何保证? 就是用宏把框架搭好,一个begin,一个end, 外部必须通过宏来调用。 begin和end分别 写一个 {, 一个}。这样如何忘记写end,就会有语法错误。 当然,代码总是人写的,再好的框架也会写错。如果那个家伙中间的代码多写了个},然后忘记写end宏。也就不报语法错误。
这种形而下的方法只是给C擦腚用的有点实际意义。真正需求是明确所有权传递。C++一个智能指针就能解决。 而且,就像我之前提过的WG14反吐槽Austin Group说的,人家压根就不考虑(考虑WG14的立场,应该是鼓励所有人)这么做,免得添乱。 [/quote] 又是一个觉得c++比c好的sb。优秀的程序员是不分语言的。最看不起那些语言之争的人。[/quote] 又是个二货C半吊子。 先艹几年代码再艹几年standization跟PLT再在这里叫。 最看不起这种说啥啥不懂一个劲ZB还YY别人需求的渣。哦,还有扯什么“语言就是工具”“学C之前一定要汇编”的战五渣以及易经厨。 C的SB地方没C艹的多,但是显然程度上没得比。再优秀的程序员也抗不过一群二B用弱智解决方案绑架需求。连语言好坏都不敢直视的只会纸上谈兵的就别JJYY浪费氧气了。
hunterzone 2014-05-05
  • 打赏
  • 举报
回复
引用 98 楼 zhao4zhong1 的回复:
单步类的实例“构造”或“复制”或“作为函数参数”或“作为函数返回值返回”或“参加各种运算”或“退出作用域”的语句对应的汇编代码几步后,就会来到该类的“构造函数”或“复制构造函数”或“运算符重载”或“析构函数”对应的C/C++源代码处。
赵老师。。。
赵4老师 2014-05-05
  • 打赏
  • 举报
回复
计算机组成原理→DOS命令→汇编语言→C语言(不包括C++)、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言(包括C++)、架构…… 对学习编程者的忠告: 眼过千遍不如手过一遍! 书看千行不如手敲一行! 手敲千行不如单步一行! 单步源代码千行不如单步对应汇编一行! 单步类的实例“构造”或“复制”或“作为函数参数”或“作为函数返回值返回”或“参加各种运算”或“退出作用域”的语句对应的汇编代码几步后,就会来到该类的“构造函数”或“复制构造函数”或“运算符重载”或“析构函数”对应的C/C++源代码处。 VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化,这样过一遍不就啥都明白了吗。 对VC来说,所谓‘调试时’就是编译连接通过以后,按F10或F11键单步执行一步以后的时候,或者在某行按F9设了断点后按F5执行停在该断点处的时候。 (Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。) 不要迷信书、考题、老师、回帖; 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实! 有人说一套做一套,你相信他说的还是相信他做的? 其实严格来说这个世界上古往今来所有人都是说一套做一套,不是吗? 不要写连自己也预测不了结果的代码!
zhousitiaoda 2014-05-05
  • 打赏
  • 举报
回复
引用 54 楼 j8daxue 的回复:
[quote=引用 50 楼 zhousitiaoda 的回复:] [quote=引用 48 楼 hunter_wwq 的回复:] [quote=引用 43 楼 ken_scott 的回复:] [quote=引用 23 楼 akirya 的回复:] [quote=引用 6 楼 hunter_wwq 的回复:] 生存期管理方面的隐忧确实是存在的,但是如果开发用户在调用我的接口时是定义的const引用型变量来获取我的返回值而不知道考虑生存期管理方面的隐忧的话,那我觉得他是C++都不会去写了。我们做的这个项目用到的两个开源项目OpenCascade和OpenSceneGraph中这种cosnt引用返回类型几乎每个类都是这样去用的,我就不知道我这样用有什么问题,使用场景都是一样的。
生存周期不是大问题,除非不懂啥叫const引用。如果这都不懂只能说还需要补习下基础。[/quote] 对,引用有续命的功能[/quote] 续命功能?你指的是赋值操作和拷贝构造吗?[/quote] 返回局部变量的const引用,这个局部变量的生存期会延长到跟引用的生存期一样长。印象中好像没记错 PS:这贴倒是跟鹰犬大人学到了很多[/quote] 这个结论来自于哪? 我看的所有书中似乎都没提到这点。[/quote] http://bbs.csdn.net/topics/390538919?page=1
饭来张 2014-05-04
  • 打赏
  • 举报
回复
引用 91 楼 FrankHB1989 的回复:
[quote=引用 89 楼 book_withc 的回复:] c,c++写出的任何代码都不是100%完美的。总有其优点和缺点。 只要判断下,选择一个优点最多的方案就好了。 比如,总是不建议从函数内部分配内存,然后返回给外面指针。这样做后,分配的内存由谁释放是个无法控制的问题。 但是,还是有很多情况可以使用这种方法。 这样做不好的原因是,内部分配,外部释放,担心外部使用的人会忘记释放。 只要能够保证外面能够正确的释放就可以。 如何保证? 就是用宏把框架搭好,一个begin,一个end, 外部必须通过宏来调用。 begin和end分别 写一个 {, 一个}。这样如何忘记写end,就会有语法错误。 当然,代码总是人写的,再好的框架也会写错。如果那个家伙中间的代码多写了个},然后忘记写end宏。也就不报语法错误。
这种形而下的方法只是给C擦腚用的有点实际意义。真正需求是明确所有权传递。C++一个智能指针就能解决。 而且,就像我之前提过的WG14反吐槽Austin Group说的,人家压根就不考虑(考虑WG14的立场,应该是鼓励所有人)这么做,免得添乱。 [/quote] 又是一个觉得c++比c好的sb。优秀的程序员是不分语言的。最看不起那些语言之争的人。
  • 打赏
  • 举报
回复
引用 93 楼 FrankHB1989 的回复:
减少对象拷贝不应该是目的。目的是使程序的意图清晰同时尽量不增加不必要的开销。不推荐都用const的理由就是因为笼统的多数情况不能预测这些情况,所以需要保留,不能一概而论。 重复一遍,这里说的是参数传const&跟直接传值之间选择一个,类似地,在能保证生存期符合预期的情况下也适用于返回值。至于const&和&之间什么时候该用什么应该是清楚的。
1 在完成功需求的情况下,减少多余的拷贝。显然lz的做法是没问题的。 2 传参数 返回值是两码事,这两个地方的const不能相提并论,放在一起比较是没有意义的。我就不明白你为啥非要参数情况套在返回值上面。
  • 打赏
  • 举报
回复
引用 90 楼 FrankHB1989 的回复:
[quote=引用 88 楼 akirya 的回复:] [quote=引用 87 楼 FrankHB1989 的回复:] [quote=引用 85 楼 akirya 的回复:] [quote=引用 84 楼 FrankHB1989 的回复:] 就算没拷贝构造,但数据也要拷贝一份,能省为啥不省?
为什么你觉得copy就不省了? 实际上很多情况下这里在乎的并不是copy不copy,而是copy-initialization,或者更一般意义上的角度上来说,call by value。 不知道你有没有注意过,为什么标准库<iterator>和<algorithm>里面的iterator和function object都是直接用T这样的裸的类型参数而不是const T&,而不管T是不是可能会有很重量级的复制开销(并且实际上也是允许了)。 理由很简单:简单性。在没有理由断定传递const T&比T一定高效或者有其它明显好处之前,这样做就是prematrue optimiazation。(而事实上如果足够小——比如小于16字节——的trivially copyable对象按字面上直观地传递引用来实现,反而因为间接操作的开销,几乎总是会更慢。) 换句话说,综合来说,省略copy不见得就“省”。所以至少在这类泛型的情况下还不如考虑把const T&省略成T。(另一方面,CBV比CBR在一些地方更自然,生存期管理也简单。) 当然,要涉及一般情况,即便是模板也不见得一定简单。所以std::bind就有了个LWG DR,最后把T改成了T&&。不过这又是另外一方面的琐事了。 [/quote] 不是一码事。 1 函数对象一般都是没有成员的 2 const的话就限制 只能调用const的成员,造成了限制。比如想用for_each来完成count_if的功能。[/quote] 1.没有成员就基本上不用特地强调函数对象了,直接函数指针就行。(啥,成员指针这奇葩?)就算如此,还是有超过一种的方式传参。 2.const的引用跟没const的引用用途差得远(不算M$那个坑爹扩展),什么时候该用什么自然清楚。CBV和CBR的差距更明显,当然不是一码事,但是在这里就是效果类似了,才会引起纠结。 只能调用const的成员也不对,考虑mutable。 [/quote] 1 函数对象可以inline,可以重载。 2 mutable属于极少使用的特性,为了写个函数对象还得用这种极少使用的特性?别忘了新手占多数,不要把本来简单的问题复杂化。[/quote] 1.只是可以,不是要求。你说inline掉的是哪里。 2.只是大多数情况没必要用,不是没用。另外,说这个和函数对象没关系,只是为了提示反思const为什么不是灵丹妙药而已。 [/quote] 在lz所提出的情况下,返回const能达到目的,并能够在多数情况下减少对象拷贝,应该推荐。 至于const在其他地方的用途,跟lz提到情况没有任何关系,如有需要在另外讨论。
FrankHB1989 2014-05-01
  • 打赏
  • 举报
回复
引用 92 楼 akirya 的回复:
[quote=引用 90 楼 FrankHB1989 的回复:] [quote=引用 88 楼 akirya 的回复:] [quote=引用 87 楼 FrankHB1989 的回复:] [quote=引用 85 楼 akirya 的回复:] [quote=引用 84 楼 FrankHB1989 的回复:] 就算没拷贝构造,但数据也要拷贝一份,能省为啥不省?
为什么你觉得copy就不省了? 实际上很多情况下这里在乎的并不是copy不copy,而是copy-initialization,或者更一般意义上的角度上来说,call by value。 不知道你有没有注意过,为什么标准库<iterator>和<algorithm>里面的iterator和function object都是直接用T这样的裸的类型参数而不是const T&,而不管T是不是可能会有很重量级的复制开销(并且实际上也是允许了)。 理由很简单:简单性。在没有理由断定传递const T&比T一定高效或者有其它明显好处之前,这样做就是prematrue optimiazation。(而事实上如果足够小——比如小于16字节——的trivially copyable对象按字面上直观地传递引用来实现,反而因为间接操作的开销,几乎总是会更慢。) 换句话说,综合来说,省略copy不见得就“省”。所以至少在这类泛型的情况下还不如考虑把const T&省略成T。(另一方面,CBV比CBR在一些地方更自然,生存期管理也简单。) 当然,要涉及一般情况,即便是模板也不见得一定简单。所以std::bind就有了个LWG DR,最后把T改成了T&&。不过这又是另外一方面的琐事了。 [/quote] 不是一码事。 1 函数对象一般都是没有成员的 2 const的话就限制 只能调用const的成员,造成了限制。比如想用for_each来完成count_if的功能。[/quote] 1.没有成员就基本上不用特地强调函数对象了,直接函数指针就行。(啥,成员指针这奇葩?)就算如此,还是有超过一种的方式传参。 2.const的引用跟没const的引用用途差得远(不算M$那个坑爹扩展),什么时候该用什么自然清楚。CBV和CBR的差距更明显,当然不是一码事,但是在这里就是效果类似了,才会引起纠结。 只能调用const的成员也不对,考虑mutable。 [/quote] 1 函数对象可以inline,可以重载。 2 mutable属于极少使用的特性,为了写个函数对象还得用这种极少使用的特性?别忘了新手占多数,不要把本来简单的问题复杂化。[/quote] 1.只是可以,不是要求。你说inline掉的是哪里。 2.只是大多数情况没必要用,不是没用。另外,说这个和函数对象没关系,只是为了提示反思const为什么不是灵丹妙药而已。 [/quote] 在lz所提出的情况下,返回const能达到目的,并能够在多数情况下减少对象拷贝,应该推荐。 至于const在其他地方的用途,跟lz提到情况没有任何关系,如有需要在另外讨论。[/quote] 减少对象拷贝不应该是目的。目的是使程序的意图清晰同时尽量不增加不必要的开销。不推荐都用const的理由就是因为笼统的多数情况不能预测这些情况,所以需要保留,不能一概而论。 重复一遍,这里说的是参数传const&跟直接传值之间选择一个,类似地,在能保证生存期符合预期的情况下也适用于返回值。至于const&和&之间什么时候该用什么应该是清楚的。
FrankHB1989 2014-04-30
  • 打赏
  • 举报
回复
引用 85 楼 akirya 的回复:
[quote=引用 84 楼 FrankHB1989 的回复:] 就算没拷贝构造,但数据也要拷贝一份,能省为啥不省?
为什么你觉得copy就不省了? 实际上很多情况下这里在乎的并不是copy不copy,而是copy-initialization,或者更一般意义上的角度上来说,call by value。 不知道你有没有注意过,为什么标准库<iterator>和<algorithm>里面的iterator和function object都是直接用T这样的裸的类型参数而不是const T&,而不管T是不是可能会有很重量级的复制开销(并且实际上也是允许了)。 理由很简单:简单性。在没有理由断定传递const T&比T一定高效或者有其它明显好处之前,这样做就是prematrue optimiazation。(而事实上如果足够小——比如小于16字节——的trivially copyable对象按字面上直观地传递引用来实现,反而因为间接操作的开销,几乎总是会更慢。) 换句话说,综合来说,省略copy不见得就“省”。所以至少在这类泛型的情况下还不如考虑把const T&省略成T。(另一方面,CBV比CBR在一些地方更自然,生存期管理也简单。) 当然,要涉及一般情况,即便是模板也不见得一定简单。所以std::bind就有了个LWG DR,最后把T改成了T&&。不过这又是另外一方面的琐事了。 [/quote] 不是一码事。 1 函数对象一般都是没有成员的 2 const的话就限制 只能调用const的成员,造成了限制。比如想用for_each来完成count_if的功能。[/quote] 1.没有成员就基本上不用特地强调函数对象了,直接函数指针就行。(啥,成员指针这奇葩?)就算如此,还是有超过一种的方式传参。 2.const的引用跟没const的引用用途差得远(不算M$那个坑爹扩展),什么时候该用什么自然清楚。CBV和CBR的差距更明显,当然不是一码事,但是在这里就是效果类似了,才会引起纠结。 只能调用const的成员也不对,考虑mutable。
  • 打赏
  • 举报
回复
引用 84 楼 FrankHB1989 的回复:
为什么你觉得copy就不省了? 实际上很多情况下这里在乎的并不是copy不copy,而是copy-initialization,或者更一般意义上的角度上来说,call by value。 不知道你有没有注意过,为什么标准库<iterator>和<algorithm>里面的iterator和function object都是直接用T这样的裸的类型参数而不是const T&,而不管T是不是可能会有很重量级的复制开销(并且实际上也是允许了)。 理由很简单:简单性。在没有理由断定传递const T&比T一定高效或者有其它明显好处之前,这样做就是prematrue optimiazation。(而事实上如果足够小——比如小于16字节——的trivially copyable对象按字面上直观地传递引用来实现,反而因为间接操作的开销,几乎总是会更慢。) 换句话说,综合来说,省略copy不见得就“省”。所以至少在这类泛型的情况下还不如考虑把const T&省略成T。(另一方面,CBV比CBR在一些地方更自然,生存期管理也简单。) 当然,要涉及一般情况,即便是模板也不见得一定简单。所以std::bind就有了个LWG DR,最后把T改成了T&&。不过这又是另外一方面的琐事了。
不是一码事。 1 函数对象一般都是没有成员的 2 const的话就限制 只能调用const的成员,造成了限制。比如想用for_each来完成count_if的功能。
  • 打赏
  • 举报
回复
引用 84 楼 FrankHB1989 的回复:
就算没拷贝构造,但数据也要拷贝一份,能省为啥不省?
为什么你觉得copy就不省了? 实际上很多情况下这里在乎的并不是copy不copy,而是copy-initialization,或者更一般意义上的角度上来说,call by value。 不知道你有没有注意过,为什么标准库<iterator>和<algorithm>里面的iterator和function object都是直接用T这样的裸的类型参数而不是const T&,而不管T是不是可能会有很重量级的复制开销(并且实际上也是允许了)。 理由很简单:简单性。在没有理由断定传递const T&比T一定高效或者有其它明显好处之前,这样做就是prematrue optimiazation。(而事实上如果足够小——比如小于16字节——的trivially copyable对象按字面上直观地传递引用来实现,反而因为间接操作的开销,几乎总是会更慢。) 换句话说,综合来说,省略copy不见得就“省”。所以至少在这类泛型的情况下还不如考虑把const T&省略成T。(另一方面,CBV比CBR在一些地方更自然,生存期管理也简单。) 当然,要涉及一般情况,即便是模板也不见得一定简单。所以std::bind就有了个LWG DR,最后把T改成了T&&。不过这又是另外一方面的琐事了。 [/quote] 不是一码事。 1 函数对象一般都是没有成员的 2 const的话就限制 只能调用const的成员,造成了限制。比如想用for_each来完成count_if的功能。
FrankHB1989 2014-04-30
  • 打赏
  • 举报
回复
引用 83 楼 akirya 的回复:
[quote=引用 80 楼 FrankHB1989 的回复:] [quote=引用 59 楼 akirya 的回复:] [quote=引用 58 楼 nklofy 的回复:] [quote=引用 51 楼 akirya 的回复:] [quote=引用 32 楼 nklofy 的回复:] [quote=引用 29 楼 akirya 的回复:] [quote=引用 27 楼 xiaohuh421 的回复:] 因为你引用的是一个对象, 而这个对象可能又不是一数据结构, 而是一个普通的类. 如果你返回了常引用, 那么就意味着, 这个对象中所有的非const类型的函数你都不能使用了, 这样就会对那个类产生影响 那些返回数据的函数就必需得定义成 const. 总之用起来反而复杂了. 反之, 如果不使用const引用, 而使用普通引用, 那完全可以在调用时, 赋值给const,. 这样程序更灵活, 对于实际编程维护带来很多方便. 但基本类库中, 比如STL, 这些是比较稳定的东西, 一旦发布, 使用它的人就不会去修改了(开放-封闭原则). 跟实际项目中是不同的. 个人观点, 有错请指正.
有点搞复杂了 比如一个对象,包含了一个位置结构体Point;,那么提供一个方法返回当前对象的位置 Point GetPoint(); const Point& GetPoint(); 两种选择。 如果需要设置那就是另外的方法。[/quote] 关键是后面Point还需不需要修改。get一般作为传值用,不是传个不能修改的引用。 假如A a得到m_A的值,后面又要改a的成员变量,要调用a的成员函数,这个const reference还真没啥用。[/quote] 能够减少一次对象拷贝构造。[/quote] 看具体应用情境。有些情况下,比如需要修改赋值后的A类对象,引用传值后还是要重新拷贝构造一个新的A类对象。 若getA用传值,那么新对象可以定义为一个引用,那拷贝的次数跟getA传引用的开销是一样的。 再比如,有的编译器,对形如A a=b.getA()是有自动优化的,不管传值还是传引用,拷贝都是一次。 当然了,传引用也不算错。只是没我们想象中那么好而已。[/quote] 对于获取值然后不修改的情况岂不是多了次构造么?能省为啥不去省呢?[/quote] 如果A能trivially copyable本身就根本不用因为这里的构造生成代码,考虑什么呢。 再加上越来越形同强制的copy elision,就更没什么好纠结的了。 如果这里还要以性能为由扯,一句prematured optimization is all root of evil就可以噎回去了。 反倒是convention(i.e.直接明确什么时候用引用什么时候不用)比较重要。 事实上光是性能的问题,也始终没有绝对的定论(包括WG21的paper里还有继续纠结的,尤其是涉及传参的aliasing的时候)。所以能做的只是大体的guildline和convention。 [/quote] 就算没拷贝构造,但数据也要拷贝一份,能省为啥不省?[/quote] 为什么你觉得copy就不省了? 实际上很多情况下这里在乎的并不是copy不copy,而是copy-initialization,或者更一般意义上的角度上来说,call by value。 不知道你有没有注意过,为什么标准库<iterator>和<algorithm>里面的iterator和function object都是直接用T这样的裸的类型参数而不是const T&,而不管T是不是可能会有很重量级的复制开销(并且实际上也是允许了)。 理由很简单:简单性。在没有理由断定传递const T&比T一定高效或者有其它明显好处之前,这样做就是prematrue optimiazation。(而事实上如果足够小——比如小于16字节——的trivially copyable对象按字面上直观地传递引用来实现,反而因为间接操作的开销,几乎总是会更慢。) 换句话说,综合来说,省略copy不见得就“省”。所以至少在这类泛型的情况下还不如考虑把const T&省略成T。(另一方面,CBV比CBR在一些地方更自然,生存期管理也简单。) 当然,要涉及一般情况,即便是模板也不见得一定简单。所以std::bind就有了个LWG DR,最后把T改成了T&&。不过这又是另外一方面的琐事了。
  • 打赏
  • 举报
回复
引用 80 楼 FrankHB1989 的回复:
[quote=引用 59 楼 akirya 的回复:] [quote=引用 58 楼 nklofy 的回复:] [quote=引用 51 楼 akirya 的回复:] [quote=引用 32 楼 nklofy 的回复:] [quote=引用 29 楼 akirya 的回复:] [quote=引用 27 楼 xiaohuh421 的回复:] 因为你引用的是一个对象, 而这个对象可能又不是一数据结构, 而是一个普通的类. 如果你返回了常引用, 那么就意味着, 这个对象中所有的非const类型的函数你都不能使用了, 这样就会对那个类产生影响 那些返回数据的函数就必需得定义成 const. 总之用起来反而复杂了. 反之, 如果不使用const引用, 而使用普通引用, 那完全可以在调用时, 赋值给const,. 这样程序更灵活, 对于实际编程维护带来很多方便. 但基本类库中, 比如STL, 这些是比较稳定的东西, 一旦发布, 使用它的人就不会去修改了(开放-封闭原则). 跟实际项目中是不同的. 个人观点, 有错请指正.
有点搞复杂了 比如一个对象,包含了一个位置结构体Point;,那么提供一个方法返回当前对象的位置 Point GetPoint(); const Point& GetPoint(); 两种选择。 如果需要设置那就是另外的方法。[/quote] 关键是后面Point还需不需要修改。get一般作为传值用,不是传个不能修改的引用。 假如A a得到m_A的值,后面又要改a的成员变量,要调用a的成员函数,这个const reference还真没啥用。[/quote] 能够减少一次对象拷贝构造。[/quote] 看具体应用情境。有些情况下,比如需要修改赋值后的A类对象,引用传值后还是要重新拷贝构造一个新的A类对象。 若getA用传值,那么新对象可以定义为一个引用,那拷贝的次数跟getA传引用的开销是一样的。 再比如,有的编译器,对形如A a=b.getA()是有自动优化的,不管传值还是传引用,拷贝都是一次。 当然了,传引用也不算错。只是没我们想象中那么好而已。[/quote] 对于获取值然后不修改的情况岂不是多了次构造么?能省为啥不去省呢?[/quote] 如果A能trivially copyable本身就根本不用因为这里的构造生成代码,考虑什么呢。 再加上越来越形同强制的copy elision,就更没什么好纠结的了。 如果这里还要以性能为由扯,一句prematured optimization is all root of evil就可以噎回去了。 反倒是convention(i.e.直接明确什么时候用引用什么时候不用)比较重要。 事实上光是性能的问题,也始终没有绝对的定论(包括WG21的paper里还有继续纠结的,尤其是涉及传参的aliasing的时候)。所以能做的只是大体的guildline和convention。 [/quote] 就算没拷贝构造,但数据也要拷贝一份,能省为啥不省?
ken_scott 2014-04-30
  • 打赏
  • 举报
回复
引用 79 楼 akirya 的回复:
[quote=引用 69 楼 ken_scott 的回复:] 如我在62L所说,我也是在《深入理解C++11:C++11新特性解析与应用》才了解到,原来C++有这个特性(不是C++11才有的,而是C++98就有的),至于这个“续命”是不是作者自己定义的一个概念,我就不知道了,也不负责哦。
const & 只对 右值有续命的功能,左值没有。
const std::string& s = std::string("sssa");
[/quote] 嗯,因为被引用的这个左值(object)的作用域肯定是 比 引用本身(const reference)的作用域 要大,所以,引用存活的时候,被引用左值肯定也是存活的(不考虑动态创建的对象),谈不上续命了
FrankHB1989 2014-04-30
  • 打赏
  • 举报
回复
哦,之前看漏了。 “说从没见过这种用法”。 嘛,这就不是不够清楚场景和需求的问题了,性质完全不一样。可以定性为单纯由于想象力和C++水平烂到没积累工程实践所需的足够常识导致的瞎指挥而已。用这个意淫“学院派”,算是性格弱点什么的帽子LZ也随便扣吧。这里你比那个架构师还强一点(至少见过了,觉得可以没问题)。
FrankHB1989 2014-04-30
  • 打赏
  • 举报
回复
引用 59 楼 akirya 的回复:
[quote=引用 58 楼 nklofy 的回复:] [quote=引用 51 楼 akirya 的回复:] [quote=引用 32 楼 nklofy 的回复:] [quote=引用 29 楼 akirya 的回复:] [quote=引用 27 楼 xiaohuh421 的回复:] 因为你引用的是一个对象, 而这个对象可能又不是一数据结构, 而是一个普通的类. 如果你返回了常引用, 那么就意味着, 这个对象中所有的非const类型的函数你都不能使用了, 这样就会对那个类产生影响 那些返回数据的函数就必需得定义成 const. 总之用起来反而复杂了. 反之, 如果不使用const引用, 而使用普通引用, 那完全可以在调用时, 赋值给const,. 这样程序更灵活, 对于实际编程维护带来很多方便. 但基本类库中, 比如STL, 这些是比较稳定的东西, 一旦发布, 使用它的人就不会去修改了(开放-封闭原则). 跟实际项目中是不同的. 个人观点, 有错请指正.
有点搞复杂了 比如一个对象,包含了一个位置结构体Point;,那么提供一个方法返回当前对象的位置 Point GetPoint(); const Point& GetPoint(); 两种选择。 如果需要设置那就是另外的方法。[/quote] 关键是后面Point还需不需要修改。get一般作为传值用,不是传个不能修改的引用。 假如A a得到m_A的值,后面又要改a的成员变量,要调用a的成员函数,这个const reference还真没啥用。[/quote] 能够减少一次对象拷贝构造。[/quote] 看具体应用情境。有些情况下,比如需要修改赋值后的A类对象,引用传值后还是要重新拷贝构造一个新的A类对象。 若getA用传值,那么新对象可以定义为一个引用,那拷贝的次数跟getA传引用的开销是一样的。 再比如,有的编译器,对形如A a=b.getA()是有自动优化的,不管传值还是传引用,拷贝都是一次。 当然了,传引用也不算错。只是没我们想象中那么好而已。[/quote] 对于获取值然后不修改的情况岂不是多了次构造么?能省为啥不去省呢?[/quote] 如果A能trivially copyable本身就根本不用因为这里的构造生成代码,考虑什么呢。 再加上越来越形同强制的copy elision,就更没什么好纠结的了。 如果这里还要以性能为由扯,一句prematured optimization is all root of evil就可以噎回去了。 反倒是convention(i.e.直接明确什么时候用引用什么时候不用)比较重要。 事实上光是性能的问题,也始终没有绝对的定论(包括WG21的paper里还有继续纠结的,尤其是涉及传参的aliasing的时候)。所以能做的只是大体的guildline和convention。
  • 打赏
  • 举报
回复
引用 69 楼 ken_scott 的回复:
如我在62L所说,我也是在《深入理解C++11:C++11新特性解析与应用》才了解到,原来C++有这个特性(不是C++11才有的,而是C++98就有的),至于这个“续命”是不是作者自己定义的一个概念,我就不知道了,也不负责哦。
const & 只对 右值有续命的功能,左值没有。
const std::string& s = std::string("sssa");
ken_scott 2014-04-30
  • 打赏
  • 举报
回复
引用 76 楼 FrankHB1989 的回复:
[quote=引用 72 楼 hunter_wwq 的回复:] [quote=引用 71 楼 ken_scott 的回复:] [quote=引用 70 楼 u013934621 的回复:] 我知道你的意思。 我其实是说如果加上析构函数。 会发现析构函数已经被调用过了(我在析构函数里给一个成员变量赋值为-10,const A & c = getA(); 运行后, c所指成员变量的值为-10,不可能是巧合啥)。 是否可以说对象已经被释放。 只是他占用的内存还能访问。 我用指针试过 也存在这种情况。
是么?但我用下面的代码: 在VS2010和codeblocks(gcc -std=c++0x -std=c++98) 得到的输出都是:

A: 0
i = 0
~A: 1
[/quote] 我分别用VC++6.0,VS2005,VS2010试了,在VS2005和VS2010下是直接A& c = A()的,VC++6.0则不是,这个续命功能可能需要编译器支持吧[/quote] 左值引用无所谓扩展临时对象生存期。A& c = A()没给你编译错误是因为VC++有个自己人都吐槽的傻×扩展。 要么const A& c = A()要么A&& c = A(),自己看着办。 [/quote] 他应该是漏写了const,没const的话,应该编译不过的
加载更多回复(80)

65,209

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧