C++ nontrival class 值传递的机制。
来源:互联网 发布:知乎周刊是什么 编辑:程序博客网 时间:2024/06/06 01:42
研究C++已经有一段时间了,我那时扔掉了手头的中文版c++ primer,开始阅读英文版,用时一年半多才勉强开完一遍,增加了一千一百多个注释,如果确认没有版权问题,我会把它共享。再给gcc提bug时,通过邮件交流得知C++标准化工作组的网站,http://open-std.org/JTC1/SC22/WG21/,后面有陆续接触了C++创始人写的书,以及他在自己home page http://www.stroustrup.com/发表的文章。也浏览Nicolai M. Josuttis关于标准库和template的书,并为其找到几处错误,还一直期待他的C++11 template相关的书籍。目前在研究GCC中C++标准库的实现,也在看lippman的 inside the c++ object model。
今天看到class作为函数参数传递的问题,解决了困扰自己很久的问题,回想起来,其实好多类似的问题,但我没有总结出来,尽管我水平不高,这些问题别人也可能碰到,总结出来总会帮助到别人的,后面我会慢慢回忆那些让我豁然开朗的情形,写出来。接下来进入正题。
在C++中,object有一种叫做memberwise的copy方式,函数参数传递就是用的这样的机制。对于类似int,char,或者c中的structure,这都不是问题,因为对于它们,memberwise copy实现的拷贝构造函数是合法的。大家都清楚,memberwise copy方式实现的拷贝构造并不总是合法的。那么如果memberwise copy不合法时,如何实现函数参数传递呢? 编译会采用下面的策略:
1、直接把作为参数的object构造在被调用的函数栈里
2、在calling function stack中构造函数参数,然后将called function parameter改写成引用形式。
GCC默认采用了第二种方式,下面是我用GDB验证的结果。
1 #include <iostream> 2 3 class test 4 { 5 private: 6 int i; 7 public: 8 test(int v):i(v){} 9 test(const test &v):i(v.i + 1){} 10 virtual void show() 11 { 12 std::cout << i << std::endl; 13 return; 14 } 15 ~test() = default; 16 }; 17 18 int foo(test v) 19 { 20 int ii = 0; 21 v.show(); 22 std::cout << ii << std::endl; 23 return 0; 24 } 25 26 int main() 27 { 28 test v(1); 29 foo(v); 30 return 0; 31 }
可执行程序gdb调式的结果
Breakpoint 1, foo (v=...) at how_class_argument_passed.cpp:20
20 int ii = 0;
(gdb) info r
eax 0xbffff588 -1073744504
ecx 0xbffff5b0 -1073744464
edx 0x2 2
ebx 0x48996000 1218011136
esp 0xbffff550 0xbffff550
ebp 0xbffff568 0xbffff568
esi 0x0 0
edi 0x0 0
eip 0x80486f2 0x80486f2 <foo(test)+6>
eflags 0x286 [ PF SF IF ]
cs 0x73 115
ss 0x7b 123
ds 0x7b 123
es 0x7b 123
fs 0x0 0
gs 0x33 51
(gdb) print &v
$1 = (test *) 0xbffff588
(gdb) f 1
#1 0x08048773 in main () at how_class_argument_passed.cpp:29
29 foo(v);
(gdb) info r
eax 0xbffff588 -1073744504
ecx 0xbffff5b0 -1073744464
edx 0x2 2
ebx 0x48996000 1218011136
esp 0xbffff570 0xbffff570
ebp 0xbffff598 0xbffff598
esi 0x0 0
edi 0x0 0
eip 0x8048773 0x8048773 <main()+65>
eflags 0x286 [ PF SF IF ]
cs 0x73 115
ss 0x7b 123
ds 0x7b 123
es 0x7b 123
fs 0x0 0
gs 0x33 51
(gdb) print &v
$2 = (test *) 0xbffff580
可以看到函数foo的stack是0xbffff550 - 0xbffff568,但是值传递的参数地址是0xbffff588,明显不在foo stack中,在main stack中。
main stack 0xbffff570 - 0xbffff598,以及调用foo的argument的地址0xbffff580。
这说明调用foo时,参数是复制了,但是复制的object依然在主调函数的栈中。也就是上面说的第二种情况。
- C++ nontrival class 值传递的机制。
- c语言按值传递的机制
- Objective-C的消息传递机制
- Objective-C的消息传递机制
- Objective-C的消息传递机制
- Objective-C的消息传递机制
- C/C++的参数传递机制
- C/C++的参数传递机制
- C/C++中参数的传递机制
- c语言的函数参数传递机制
- c语言引用传递的机制
- Java的值传递机制
- 方法的参数传递机制——值传递机制
- Java方法参数的传递机制,值传递?引用传递?
- c语言 按值传递机制和按引用传递机制
- 深入剖析C/C++函数的参数传递机制
- 深入剖析C/C++函数的参数传递机制
- 深入剖析C/C++函数的参数传递机制
- BOM和DOM
- WebKit官方又开始发布源代码压缩包了
- 断电!!!oracle oracle initialization or shutdown
- ThinkPad T430i黑苹果Yosemite 10.10.3成功显卡驱动
- 简单二维数组转置问题
- C++ nontrival class 值传递的机制。
- wifi direct/p2p流程分析 基于android 5.1
- Eclipse+pydev插件-----python开发环境
- 自定义ViewPagerIndicator(下)
- 1084. Broken Keyboard (20)
- 创建java线程方式之三实现Callable接口
- PHP实现留言本代码
- 差分约束系统
- hdu5011Game nim博弈