c++之拷贝构造函数调用时机

时间:2023-03-09 16:56:53
c++之拷贝构造函数调用时机

test1:

 #include<iostream>
using namespace std;
class Copy_construction {
public:
Copy_construction(int a = )
{
this->a = a;
cout << "这是有默认参数的构造函数!\n";
}
Copy_construction(const Copy_construction &obj)
{
cout << "这是拷贝构造函数!\n";
a = obj.a;
}
~Copy_construction()
{
cout << "一个对象被析构了!\n";
}
private:
int a;
};
void fuc(Copy_construction t)
{
cout << "fuc函数!\n";
}
void play_empty(void)
{
Copy_construction t1;//调用有默认实参的构造函数
Copy_construction t2 = t1;//调用拷贝构造函数
Copy_construction t3(t2);//调用拷贝构造函数
cout << "_________________\n";
fuc(t3);//实参初始化形参,调用拷贝构造函数
}
int main()
{
play_empty(); cout << "hello world!\n";
return ;
}

运行结果

c++之拷贝构造函数调用时机

test2:

修改fuc函数为引用或者指针类型。

 void fuc(Copy_construction *t)
{
cout << "fuc函数!\n";
} void fuc(Copy_construction &t)
{
cout << "fuc函数!\n";
} /*****引用或者指针类型调用时不会调用拷贝构造函数****/

test3:

匿名对象的出现:

 #include<iostream>
using namespace std;
class Copy_construction {
public:
Copy_construction(int a = )
{
this->a = a;
cout << "这是有默认参数的构造函数!\n";
}
Copy_construction(const Copy_construction &obj)
{
cout << "这是拷贝构造函数!\n";
a = obj.a;
}
~Copy_construction()
{
cout << "一个对象被析构了!\n";
}
private:
int a;
};
Copy_construction fuc(void)
{
cout << "fuc函数!\n";
Copy_construction A;
return A;//调用拷贝构造函数,生成匿名对象
}//运行到该处,先析构对象A,匿名对象是否析构要看怎么去接
//如下所示直接调用fuc()则此时匿名对象会被立即析构
void play_empty(void)
{
fuc();
}
int main()
{
play_empty(); cout << "hello world!\n";
return ;
} 如果直接显示调用构造函数,要看怎么去接这个函数, Copy_construction(1);调用之后马上执行析构匿名对象, Copy_construction  T= Copy_construction(1);不会马上析构还会转正。

test4:

修改fuc函数的返回类型为引用或者指针:

 Copy_construction *fuc(void)
{
cout << "fuc函数!\n";
Copy_construction A;
return &A;
} Copy_construction &fuc(void)
{
cout << "fuc函数!\n";
Copy_construction A;
return A;
} /********返回类型为指针或者引用不会调用拷贝构造函数*********/

test5:

改变接匿名对象的方式:

 #include<iostream>
using namespace std;
class Copy_construction {
public:
Copy_construction(int a = )
{
this->a = a;
cout << "这是有默认参数的构造函数!\n";
}
Copy_construction(const Copy_construction &obj)
{
cout << "这是拷贝构造函数!\n";
a = obj.a;
}
~Copy_construction()
{
cout << "一个对象被析构了!\n";
}
private:
int a;
};
Copy_construction fuc(void)
{
cout << "fuc函数!\n";
Copy_construction A;
return A;//调用拷贝构造函数,产生匿名对象
}//析构对象A,根据下面代码的接匿名对象的方式,
//此时匿名对象不仅不会马上析构,还会转正成为对象B
//从c++设计哲学上来说,这也是提高效率的一种方式,这样的设计是合理的,因为你想创建对象B,我就不用再新开辟内存了,直接用之前的匿名对象代替
void play_empty(void)
{
Copy_construction B=fuc();//这里不会调用拷贝构造函数,匿名对象直接转正了
cout << "匿名对象转正!\n";
}
int main()
{
play_empty(); cout << "hello world!\n";
return ;
}

test6:

再改变接匿名对象的方式,重写play_empty()函数:

void play_empty(void)
{
Copy_construction B;
B= fuc();
cout << "匿名对象不会转正!\n";
} //如上所示代码,此时对象B会开辟内存,在用返回的匿名对象赋值给B,将会在赋值完成之后立即析构匿名对象,这个时候匿名对象不会转正。

summary:以下情况会调用拷贝构造函数

1.直接初始化和拷贝初始化时

2.将一个对象作为实参传递给一个非引用或非指针类型的形参时

3.从一个返回类型为非引用或非指针的函数返回一个对象时

4.用花括号列表初始化一个数组的元素或者一个聚合类(很少使用)中的成员时。