拷贝构造函数的调用时机:
以下代码段:
class Person
{
public:
Person(int age, std::string name):
m_age(age), m_name(name)
{
qDebug() << "construct!" << this << m_name.c_str() << m_age;
}
Person(const Person& other)
{
this->m_name = other.m_name;
this->m_age = other.m_age;
qDebug() << "copy construct!" << this;
}
Person& operator=(const Person& other)
{
qDebug() << "operator =" << this;
if (&other == this)
return *this;
this->m_name = other.m_name;
this->m_age = other.m_age;
return *this;
}
Person(Person&& other)
{
this->m_name = other.m_name;
this->m_age = other.m_age;
qDebug() << "move construct!" << this;
}
Person &operator=(Person && other)
{
qDebug() << "move operator =" << this;
if (&other == this)
return *this;
this->m_name = other.m_name;
this->m_age = other.m_age;
return *this;
}
~Person()
{
qDebug() << "destruct!" << this;
}
private:
int m_age;
std::string m_name;
};
//Person类作为Test类的成员变量
class Test
{
public:
Test(): p(24, "test")
{
}
~Test()
{
}
Person& GetPerson() // 返回成员变量的引用
{
return p;
}
void onTest()
{
Person result1 = GetPerson();
//这里result1和成员变量p并不是同一个对象
//这里的result1会通过成员变量p调用拷贝构造函数来构造,出了result1的作用域就会析构
Person result2 = result1; //拷贝构造函数, 用来创建 result2 对象
result2 = result1; //赋值运算符, result2 对象是已经存在的
Person& result3 = GetPerson();
//这里result3就是成员变量p; 因为这里使用引用的方式接收返回值;result的生命周期同p一样,
Person result4 = std::move(result1); //移动构造函数
result4 = std::move(result2); //移动赋值运算符
}
private:
Person p; //Person类没有无参构造函数,所以必须在初始化列表进行初始化
Person p(10, "test"); //报错,C++不允许使用小括号()在类内初始化成员变量(但是可以使用小括号在类的初始化列表进行成员变量的初始化); 因为此处被解释为函数声明
Person p{20, "yxj"}; //ok 大括号统一初始化, 调用构造函数
Person p2 = p; //OK 拷贝构造
Person p = Person{20, "yxj"}; //ok 构造函数
Person p = Person(20, "yxj"); //ok 构造函数
Person* p = new Person(2, "x"); //ok 构造函数
Person* p = new Person{2, "x"}; //ok 构造函数
};
拷贝构造函数的调用时机:
1.以值传递形式传递函数参数
2.函数的返回值是值传递形式,哪怕是函数返回值是引用形式传递,如果不是以引用形式接收,也会进行拷贝(见下例result1
对象)
3.以一个对象来构造另外一个对象
构造函数的调用时机:
1.使用 = 来进行对象的创建时,如以上例子中的 result2
2.在声明时进行初始化,如上p3
、p4
对象