C++拷贝构造函数调用时机

1、当用一个对象去初始化同类的另一个对象时,会引发拷贝构造函数的调用

fun f2;
fun f1 = f2;

// 注意下面不会调用拷贝构造函数(会调operator=函数),注意字眼“初始化”
fun f1, f2;
f1 = f2;

 

2、作为形参的对象,使用拷贝构造函数初始化

fun f1;
fun f2{f1};  //  调用拷贝构造

fun f1;
fun* f2 = new fun(f1);  // 调用拷贝构造

// 如果接受对象为引用,
则不会调用拷贝构造函数
fun f1;  // 不会调用拷贝构造函数
fun& f2{f1};

 

3、如果函数返回的是类的对象,那么函数返回时,类的拷贝构造函数会被调用

fun getFun()
{
  fun f;  
  return f;     //  调用拷贝构造函数,且返回值为右值
} 

// 【延伸】
fun f1;
fun&& f2 = f1.getFun();  // getFun()返回值为右值,通过右值引用"&&",将其生命周期变得和f2一样,减少内存重复开辟和释放的开销
const fun&f3 = f1.getFun();  // 也可以常量左值"const T&"来绑定,常量左值可以绑定任何值,缺点是只能读不能更改
// 【延伸】


// 如果接受类型变为引用,则不会调用拷贝构造函数
fun& getFun()  //  不会调用拷贝构造函数
{
  fun f;  
  return f;     
}         //  离开该代码块后会f会调用析构函数,地址虽然得到了,但是里面成员变量值都不对了

 

4、用花括号列表初始化一个数组中的元素或一个聚合类中的成员

fun f1;
fun f2;
fun f3;
fun funs[] = {f1, f2, f3};   //  调用三次拷贝构造函数

 

5、 初始化标准库容器或者调用其insert或push成员时

fun f1;
fun f2;

std::vector<fun> v;
v.push_back(f1);
v.push_back(f2);


// 若不想触发拷贝构造想触发移动构造
//  可以使用std::move(),或者emplace_back,推荐emplace_back
//  前提是定义了移动构造函数
fun f1;
fun f2;

std::vector<fun> v;
v.push_back(std>>move(f1));
v.emplace_back(f2);

 

扩展:

禁止拷贝构造函数调用的方法

fun(const fun&) = delete;

 

posted @ 2021-10-07 16:10  补码  阅读(114)  评论(0编辑  收藏  举报