拷贝构造函数调用时机
C++中拷贝构造函数的调用时机有三种:
1 使用一个已经创建完毕的对象来初始化一个新对象
2 值传递的方式给函数参数传值
3 以值方式返回局部对象
class Person
{
public:
Person()
{
cout << "Person默认构造函数调用" << endl;
}
Person(int age)
{
cout << "Person有参构造函数调用" << endl;
m_Age = age;
}
Person( const Person& p)
{
cout << "Person拷贝构造函数调用" << endl;
m_Age = p.m_Age;
}
~Person()
{
cout<<"Person析构函数调用" << endl;
}
int m_Age;
};
//1 使用一个已经创建完毕的对象来初始化一个新对象
void test01()
{
Person p1(20);
Person p2(p1);
cout << "p2的年龄为:" << p2.m_Age << endl;
}
//2 值传递的方式给函数参数传值
void doWork(Person p)
{
//因为值传递 所以会有拷贝构造函数的调用
}
void test02()
{
Person p;
doWork(p);
}
//3 以值方式返回局部对象
Person doWork2()
{
Person p1;
return p1;//值返回
}
void test03()
{
Person p = doWork2();
}
int main()
{
// test01();
// test02();
test03();
system("pause");
return 0;
}
构造函数的调用规则
默认情况下,C++编译器至少给一个类添加3个函数(每一个都会有)
1 默认构造函数(无参,函数体空)
2 默认析构函数(无参,函数体空)
3 默认拷贝构造函数,拷贝属性值
构造函数调用规则 :
- 如果用户定义有参构造函数,C++则不再提供默认无参构造,但会提供默认拷贝函数。
- 如果用户定义拷贝构造函数,C++不会再提供其他构造函数。
class Person
{
public:
Person()
{
cout << "Person默认构造函数调用" << endl;
}
~Person()
{
cout<<"Person析构函数调用" << endl;
}
Person(int age)
{
m_Age = age;
cout << "Person有参构造函数调用" << endl;
}
Person(const Person& p)
{
cout << "Person拷贝构造函数调用" << endl;
m_Age = p.m_Age;
}
int m_Age;
};
void test01()
{
Person p;//默认
p.m_Age = 18;
Person p2(p);//拷贝
cout << "p2的年龄为:" << p2.m_Age << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
如果注释掉拷贝构造函数
class Person
{
public:
Person()
{
cout << "Person默认构造函数调用" << endl;
}
~Person()
{
cout<<"Person析构函数调用" << endl;
}
Person(int age)
{
m_Age = age;
cout << "Person有参构造函数调用" << endl;
}
/*Person(const Person& p)
{
cout << "Person拷贝构造函数调用" << endl;
m_Age = p.m_Age;
}*/
int m_Age;
};
void test01()
{
Person p;//默认
p.m_Age = 18;
Person p2(p);//拷贝
cout << "p2的年龄为:" << p2.m_Age << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
则会缺少一个拷贝构造函数的打印,但是构析函数打印的数量并没有变,因为编译器会自动编写一个拷贝构造函数:m_Age = p.m_Age;
如果再加一个函数
void test02()
{
Person p;
}
再注释掉默认构造函数
则会报错:
因为代码中有 有参构造函数,所以不会在自动提供默认构造函数。
若 写了有参构造函数,即使没有拷贝构造函数,编译器虽然不提供默认构造函数,但是会提供拷贝构造函数。
test01()
{
Person p(28);
Person p2(p);
}
如果写了拷贝构造函数,编译器就不再提供其他普通的构造函数。
会报错。