一:程序转化语义
1.我们写的代码。编译器会对代码进行拆分,拆分成编译器更容易理解和实现的代码
二:定义时初始化对象
class A{
public:
int i;
A(const A& tmpx){
i = tmpx.i;
cout << "拷贝构造函数被调用" <<endl;
}
A(){
i = 0;
cout << "构造函数被调用" <<endl;
}
};
int main(){
A a1;
a1.i = 15;
A a2 = a1;
A a3(a1);
A a4 = (a1);
//从编译器角度来说 这一行会被拆分成两个步骤
// A a4; // 编译器只是顶一个一个对象,并会调用A类构造函数
// a4.A::A(a1) // 编译器 直接调用对象的拷贝构造函数
}
三:
class A{
public:
int i;
A(const A& tmpx){
i = tmpx.i;
cout << "拷贝构造函数被调用" <<endl;
}
A(){
i = 0;
cout << "构造函数被调用" <<endl;
}
~A(){
cout << "析构函数被调用" <<endl;
}
};
void func(A a){ // 传真值 调用拷贝构造函数
return
}
int main(){
A a0;
func(a0);// 构造函数 拷贝构造函数 析构函数 析构函数 // 现代编译器
// 一些老版本的编译器会先生成一个临行对象然后将func 改为引用传值 然后析构
}
四:
class A{
public:
int i;
A(const A& tmpx){
i = tmpx.i;
cout << "拷贝构造函数被调用" <<endl;
}
A(){
i = 0;
cout << "构造函数被调用" <<endl;
}
`A(){
cout << "析构函数被调用" <<endl;
}
};
A func(){
A a; // 构造函数
return a // 产生一个临时对象 并把a的内容拷贝构造给临时对象返回
// 然后调用析构函数 析构 a
}
int main(){
A a0 = func();
} // 析构函数 析构a0
// 编译器:
/*
func()被改成:
void func(A &my_a){
A a0; // 在编译器里 这里不会调用构造函数
//... 处理a0这个对象
my_a.A::A(a0); // 调用拷贝构造函数
return ;
}
A a; // 只是定义一个对象 不会调用构造函数
func(a) //
*/
五:
class A{
public:
int i;
A(const A& tmpx){
i = tmpx.i;
cout << "拷贝构造函数被调用" <<endl;
}
A(){
i = 0;
cout << "构造函数被调用" <<endl;
}
`A(){
cout << "析构函数被调用" <<endl;
}
void Afunc(){
cout << "A的 func()"
}
};
A func(){
A a;
return a
}
int main(){
func().Afunc();
} // 析构函数 析构a0
/*
编译器:
void func(A &my_a){
A a0; // 在编译器里 这里不会调用构造函数
//... 处理a0这个对象
my_a.A::A(a0); // 调用拷贝构造函数
return ;
}
A a;
(func(my),my).Afunc();
// 逗号表达式,先计算表达式1, 然后在计算表达式2 整个表达式的结果就是表达式2的值
*/
六:
class A{
public:
int i;
A(const A& tmpx){
i = tmpx.i;
cout << "拷贝构造函数被调用" <<endl;
}
A(){
i = 0;
cout << "构造函数被调用" <<endl;
}
`A(){
cout << "析构函数被调用" <<endl;
}
void Afunc(){
cout << "A的 func()"
}
};
A func(){
A a;
return a
}
int main(){
A(*a0)() // 函数指针
a0 = func;
a0().functest();
}
/*
编译器:
func()被改成:
void func(A &my_a){
A a0; // 在编译器里 这里不会调用构造函数
//... 处理a0这个对象
my_a.A::A(a0); // 调用拷贝构造函数
return ;
}
main:
A a;
void (*a0)(A &); //func 被编译器添加引用参数 void函数
a0 = func();
a0(a);
a.functest;
*/