我们都知道, 函数中的局部变量在函数返回时, 要被销毁. 但在实际的编译运行过程中, 编译器进行了优化, 执行过程并不按照标准步骤进行.
0. 准备工作
编写测试用的Animal类, 每个Animal对象有一个唯一的标识, Animal类的实现为(获取本文中的源码):
const bool DEBUG = true;
typedef unsigned int UINT32;
class Animal {
public:
Animal();
explicit Animal(const std::string &animalName);
Animal(const Animal &rhs);
virtual ~Animal();
inline UINT32 getID() const;
private:
static UINT32 idCount;
static std::ostream &out;
const UINT32 ID;
std::string name;
};
每个成员函数均有相应的输出信息, 以便了解程序的执行过程. 现列出复制构造函数的实现(获取本文中的源码):
Animal::Animal(const std::string &animalName)
: ID(idCount++), name(animalName) {
if (DEBUG) {
out << "Animal::Animal(std::string &animalName), ID=" << ID
<< ", name=" << name << std::endl;
}
}
1. 测试: 最简单的测试
下面以最简单的例子来测试编译器的优化程度, 例子代码为(获取本文中的源码):
int main() {
void test1();
test1();
return 0;
}
void test1() {
Animal test1_fun1();
Animal a = test1_fun1();
}
Animal test1_fun1() {
return Animal("kitty");
}
在编译运行之前, 先来分析一下代码: 首先, 在函数test1_fun1中创建一个临时变量, 估且称其为temp1, 函数test1_fun1返回一个Animal类型的变量, 在退出test1_fun1函数前, 将temp1复制一份(调用复制构造函数), 称新复制的对象为temp2(作用域为main函数), 然后销毁临时变量temp1, 在main函数中, 调用a的复制构造函数(参数为temp2)进行初始化. 销毁临时变量temp2. 销毁变量a.
但实际的运行结果(VS2010, g++4.4.3)为:
Animal::Animal(std::string &animalName), ID=0, name=kitty
Animal::~Animal(), ID=0
两个Animal变量被省略了.
2. 测试: 简单的测试
修改上面test1和test1_fun1函数, 函数体中的内容改为(获取本文中的源码):
void test1() {
Animal test1_fun1();
Animal a = test1_fun1();
cout << a.getID() << endl;
}
Animal test1_fun1() {
Animal a("kitty");
return a;
}
结果会有不同吗? 请看实际运行的结果:
VS2010的运行结果为:
ID=0的对象是test1_fun1函数中的局部变量a, 在test1_fun1函数返回后, ID=0的局部变量没有被销毁, 而是用来初始化test1中的变量, 初始化完之后, ID=0的变量被销毁.
g++4.4.3的运行结果为:
Animal::Animal(std::string &animalName), ID=0, name=kitty
0
Animal::~Animal(), ID=0
本文中所用到的所有源码, 下载地址: http://163.fm/K2kZ9VK 提取码:9YRcWGQz
若下载次数达到上限, 请留言或通过邮件(njnu_mjn#126.com, #改为@)联系我