临时对象的隐蔽性与野指针不崩之谜

C++危险众所周知,项目中写代码写得天昏地暗的时候就容易踩陷阱。不是我故意耍小聪明,是进度的紧迫性和头脑的疲惫程度导致我写了这样的代码(代码经过简单处理,隐去复杂性以及不涉密。^_^):

 

char* tmpS=const_cast<char*>(string("hello").c_str());
cout<<tmpS<<endl;

 

输出什么?"hello"。多悲剧的回答,答案是仅有一个换行符而已。

因为临时对象string在调用流的时候析构掉了!(这个结论最后有代码验证。)

 

所以这种情况就正常了:

cout<<const_cast<char*>(string("hello").c_str())<<endl;

 

疑问在继续滋生。析构?那tmpS指向的内存没了,流调用的时候为何不会crash?对stl熟悉的朋友这时醒悟了,因为大部分string底层实现有用内存池。如果你模拟写一个string而不用内存池,保证连人带机一起在老板面前崩溃。况且,根据string的实现,如果缓冲用大了,string就不用内存池,另外再分配,这时内存用完了也会很快释放,一样会导致崩溃。

 

最后好戏终于上演:

// TestString.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <string.h> #include <iostream> #include <string> #include <vector> using namespace std; //模拟std::string使用的内存池 char MemPool[256]={0}; //模拟std::string class STR { public: STR(char* s) { ms=MemPool; memcpy(ms,s,strlen(s)>=256?255:strlen(s)); } ~STR() { memset(MemPool,0,sizeof(MemPool)); } char* getStr() { return ms; } private: STR(const STR&); STR& operator=(const STR&); char* ms; }; int _tmain(int argc, _TCHAR* argv[]) { //临时对象STR没析构 cout<<"1:"<<STR("hello world").getStr()<<endl; //临时对象STR没析构 char* tmpS=STR("hello world").getStr(); //临时对象STR已经析构 cout<<"2:"<<tmpS<<endl; cin.get(); return 0; }

 

你可能感兴趣的:(临时对象的隐蔽性与野指针不崩之谜)