题目:
1、请写出下列程序运行结果
#include<iostream>
using namespace std;
class CConAndDecon {
public:
CConAndDecon(int value) {
m_data = value;
cout << "Object " << m_data <<" constructor" <<endl;
}
//拷贝构造函数
CConAndDecon(const CConAndDecon &other) {
m_data = other.m_data - 1 ;
cout << "Object " << m_data <<" copy constructor" <<endl;
}
//复制函数 注意和拷贝构造函数的区别 以及他们分别在什么情况下被调用
CConAndDecon operator=(const CConAndDecon &right) {
if( this != &right )
{ m_data = right.m_data + 1 ;
cout << "Object 's new value is " << m_data <<" " <<endl;
}
return *this;
}
~CConAndDecon()
{ cout <<"Object " << m_data << " destructor" << endl; }
private:
int m_data;
};
void Func(CConAndDecon x);
int main()
{
CConAndDecon *p = new CConAndDecon(10);
static CConAndDecon c1( 20);
Func(*p); delete p;
return 0;
}
void Func(CConAndDecon x)
{
static CConAndDecon c1 = x;
// 定义时的等号是相当于调用的是该对象的拷贝构造函数
//这里在调用拷贝构造函数的时候会根据等号后面的类型
//来确定调用那一个拷贝构造函数
//
// 在定义之后的等号是调用的是该对象复制构造函数
CConAndDecon c2 = c1;
//注意想构造的后释放 静态的等程序运行结束以后在释放
}
我相信大部分初学者在看到这道题的时候就晕了,我也是在看到这道题后对着一头雾水,后来我拿到电脑上实验
在想了想,终于有一点思路了.
下面是我对这道题目的理解:
这是测试结果,我用的是g++编译器
这一道看似简单的题目涉及好多的知识点,下面是我画的一张该程序的对象创建析构顺序图
1. CConAndDecon *p=new CConAndDecon(10);
在堆上创建一个新的CConAndDecon对象 调用的是一个参数的构造函数
输出 Object 10 constructor
2. static CConAndDecon c1(20);
调用CConAndDecon 类的一个参数的构造函数 构造出一个新的对象c1 .
输出 Object 20 copy constructor
注意这里的static关键字, static作用是保持变量内容的持久。存储在静态数据区的变量会在函数刚开始运行时就完成初始化,也是唯一的一次初始化。static 变量的生命周期是进程的从创建到进程结束.
3,4. Func(*p) 进入函数Func中 这里在传参的时候会调用拷贝构造创建一个新的CConAndDecon对象(形参)
输出 Object 9 copy constructor
5. CConAndDecon c1=x;构造一个新的静态的CConAndDecon对象 调用的是拷贝构造函数.
输出 Object 8 copy constructor
6.构造局部的 CConAndDecon 变量 c2 .
7.Func 函数结束 对象c2的生命周期结束调用c2的析构函数.
形参对象的生命周期结束调用该形参对象的析构函数.
这里相同代码块(即{}之间)的非静态对象的析构顺序和构造顺序相反:先构造的后析构.
8. delete p; 用delete关键字 销毁p指针所指向的对象.
9. return 0; 进程结束静态变量的生命周期结束, 释放静态的变量(释放顺序和构造顺序相反).