打开word2007弹出未设置对象变量_深度理解:如何返回一个CString对象

考察以下程序片段

7d61496996822e52644094ac97db691d.png

执行结果

f743c11b86e16d22c018153767a553b5.png

代码解析

1) 先看GetString1。这个函数,是内部定义了一个CString对象,其对象是一个栈变量,虽然我们在函数内部对这个CString对象进行了设置,但是,一旦函数GetString1调用完毕,这个CString对象也随即被销毁,所以,这里返回的是类型为LPCTSTR的字符串指针,实际上这个指针指向了一片被销毁了的栈空间。

2) 当我们使用同样的LPCTSTR 变量去接GetString1函数的返回值时,没有其他额外隐藏的操作,程序直接了一次指针赋值。

LPCTSTR psz1 = GetString1();

这里的psz1也会同样的指向一片被销毁了的内存空间,所以,我们这里打印的内容时乱码,也即这片被销毁了的内存空间上的随机数据。

3) 当我们使用CString对象去接GetString1函数的返回值时,情况并没有好多少。

CString str1 = GetString1();

当GetString1返回一个LPCTSTR的指针并赋值给str1时,会自动调用CString对象的构造函数,这里的传给CString对象的构造函数的参数已经是一个销毁了的内存空间的指针,不幸的是,编译器并不会做此项检查,CString对象依然能构造成功,但是其内容同样是随机乱码。

5927c9cd7fdd823d47b07ae706bc3d75.png

4) 然后我们看GetString2函数。这个函数和GetString1类似,唯一不同之处,是其返回值是一个CString对象。这里返回的CString对象,意味着函数返回时,会调用CString对象的拷贝构造函数创建一个临时的CString对象并返回它。

952577b4d0871c2b8af6fc14377ed7b9.png

5) 当我们尝试使用LPCTSTR类型的指针去接GetString2的返回值时,虽然GetString2返回了一个基于栈上CString变量拷贝构造的临时CString对象,但是,临时CString对象出了GetString2的作用域后也会随即销毁,导致的结果,就是我们用来接收返回值的指针变量指向了一片被销毁的内存空间,所以,这里同样的弹出了乱码。

LPCTSTR psz2 = GetString2();

6) 终于可以讨论最后一种情况了,这也是程序正常工作的唯一一种情况。

CString str2 = GetString2();

我们不再使用LPCTSTR类型的指针接收函数发返回值了,而是使用CString类型去接收一个返回CSring对象的函数的返回值(好像有点绕)。那么,这里边发生了什么事情呢?

GetString2按值返回了一个CString临时对象,赋值给str2变量时,现代编译器执行了N(amed)RVO优化(返回值优化)。所以,这里我们在进行单步调试的时候,赋值动作是一次性就执行完毕了,并不需要调用赋值运算符了。

结论

1) 返回小型对象的成本会由编译器RVO吸收,所以,适当的情况下,可以按值返回小型对象。但是,对于大型复杂的对象,还是建议返回指向对象的引用或指针,注意了,永远不要试图返回一个指向临时对象的引用或指针。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值