聊聊C++临时对象的析构时间点------顺便再次提醒大家谨慎使用string的c_str方法
来源:互联网 发布:abaqus软件介绍 编辑:程序博客网 时间:2024/05/19 10:38
C++临时对象的析构?这不是很简单么?其实没那么简单。 我们先看看如下程序吧:
#include <iostream>#include <string>using namespace std;string test(){return "abc";}int main(){const char *p = test().c_str();cout << p << endl;return 0;}你可能迫切地期待结果为:abc, 其实不然。 为了简便起见, 我们简化一下上述程序:
#include <iostream>#include <string>using namespace std;int main(){const char *p = string("abc").c_str();cout << p << endl;return 0;}注意, 结果不是abc. 为什么呢? 我先直接说吧:string("abc")是一个临时对象, 在执行完const char *p = string("abc").c_str();这个语句后, 临时对象就析构了, 也就是说p指向的区域中的值变了。 所以, 结果自然不是abc.
这就引出了如下问题: 临时对象是何时析构的呢? 我们先看一个程序:
#include <iostream>#include <string>using namespace std;class A{public:A(){cout << "A constructor" << endl;}~A(){cout << "A destructor" << endl;}};int main(){A(); // 临时对象printf("end xxx\n");printf("end yyy\n");return 0;}稍微懂一点C++的人会说, 结果是:
A constructor
end xxx
end yyy
A destructor
其实, 上述结果是错误的, 真正的结果是:
A constructor
A destructor
end xxx
end yyy
看来, 在执行完第一个语句后, 临时对象A()就析构了, 我们来看看汇编, 验证一下吧:
我们看到, 临时对象确实是在printf之前析构的。
好, 我们接着看:
#include <iostream>#include <string>using namespace std;class A{public:A(){cout << "A constructor" << endl;}~A(){cout << "A destructor" << endl;}};int main(){A(), // 注意, 是逗号运算符printf("end xxx\n");printf("end yyy\n");return 0;}运行结果为:
A constructor
end xxx
A destructor
end yyy
不要惊讶, 查看汇编代码就知道, 临时对象是在 printf("end xxx\n");后析构的。
继续看代码:
#include <iostream>#include <string>using namespace std;class A{public:A(){cout << "A constructor" << endl;}~A(){cout << "A destructor" << endl;}};int main(){A(), // 注意, 是逗号运算符printf("end xxx\n"), // 注意, 是逗号运算符printf("end yyy\n");return 0;}运行结果为:
A constructor
end xxx
end yyy
A destructor
不要惊讶, 查看汇编代码就知道, 临时对象是在 printf("end xxx\n");后析构的。
由此可见, 临时对象是在遇到其后的第一个分号(语句结束处)析构的。
好, 我们再看看:
#include <iostream>#include <string>using namespace std;int main(){const char *p = string("abc").c_str(); // 临时对象在执行完该句后析构了cout << p << endl; // 此时p指向垃圾值return 0;}一切一目了然。
大家在使用临时对象的时候要留个心眼, 尤其是使用string的c_str时, 一旦出错, 经常排查半天, 最后才发现栽倒在此处。 鉴于容易出错, 最后, 我们再看一眼吧:
#include <iostream>#include <string>using namespace std;int main(){const char *p = (string("abc") + string("def")).c_str(); // 临时对象在执行完该句后析构了cout << p << endl; // 此时p指向垃圾值return 0;}
OK, 本文先到此为止。
备注: 在上面的程序中, 我使用的编译器是VC++6.0, 后来网友“时光”提醒我, g++的编译器会有不同的表现。 在此, 感谢“时光”。 另外, 为了写出高质量的可移植代码, 仍需要注意避免使用临时string对象的c_str方法。
- 聊聊C++临时对象的析构时间点------顺便再次提醒大家谨慎使用string的c_str方法
- 关于string.c_str()的那点事
- C++string类的c_str()函数
- string的c_str()函数
- C++中string类对象的成员函数c_str()与C语言中字符串的联系
- 周末能回家,太幸福了;顺便提醒大家要备份自己的重要数据哦
- 谨慎使用String作为HashMap的Key
- 谨慎使用String作为HashMap的Key
- 谨慎使用String作为HashMap的Key
- 为什么是string::size_type而不是int?---顺便聊聊无符号数和负数的比较
- String 类 的c_str()函数
- 透析string的c_str()函数
- c_str()的使用
- c_str的使用
- C/C++:string.c_str()
- 谨慎使用SocketChannel的read方法
- C#的一些谨慎点!
- 关于string中data()和c_str()函数的几点区别
- IBM Bluemix云平台24小时应用开发挑战赛参赛作品详解
- C++数据在内存中的存放的三个区域全局数据区,堆和栈
- NFC 浅析(一)
- Leetcode--MaximumGap
- Linux下select, poll和epoll IO模型的详解
- 聊聊C++临时对象的析构时间点------顺便再次提醒大家谨慎使用string的c_str方法
- 构造函数调用规则研究
- HttpUrlConnection retryPost 重发
- CentOS7 下安装telnet服务
- Android实现双进程守护
- 软件测试基本内容概述
- 32位操作系统和64位操作系统的数据类型大小
- GNU Sed - Sed替换入门
- 15HD_OJ——Tian Ji -- The Horse Racing