</div>
<!--一个博主专栏付费入口-->
<!--一个博主专栏付费入口结束-->
<link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-4a3473df85.css">
<link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-4a3473df85.css">
<div class="htmledit_views" id="content_views">
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方法。
</div>
<!--一个博主专栏付费入口-->
<!--一个博主专栏付费入口结束-->
<link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-4a3473df85.css">
<link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-4a3473df85.css">
<div class="htmledit_views" id="content_views">