c++构造/拷贝构造函数初始化变量*
#include <iostream>
#include <string>
using namespace std;
class Person {
public:
int id;
string name;
public:
Person() {
this->id = 200;
cout << "None param constructor" << endl;
}
/* explicit */ Person(int id) {
cout << "One param constructor" << endl;
this->id = id;
}
Person(int id, string name) {
this->id = id;
this->name = name;
cout << "Two params constructor" << endl;
}
// 如果参数不加const, 这种Person pp4 = Person(1, "qiumc");写法会报错,因为Person(1, "qiumc")产生一个临时右值,
// 临时右值在通过copy构造函数赋值给左值(copy构造函数的参数)的时候,不能赋值给非const的左值。
Person(const Person& p) {
this->id = p.id;
this->name = p.name;
cout << "copy constructor" << endl;
}
Person(Person&& p) {
this->id = p.id;
this->name = p.name;
cout << "move constructor" << endl;
}
};
/**
* @brief
* 整形初始化的几种方式
*/
void TestIntInit() {
// case1
int i1 = 100;
// case2
int i2(100);
int i3{100};
// case3
int i4 = int(100);
int i5 = int{100};
// case4
int i6 = {100};
}
/**
* @brief
* 有参构造函数的几种写法
*/
void TestPersonParamInit() {
// case1
// 这里发生了隐式转换,如果在单个参数构造函数前,加上explicit,将禁止这种隐式转化
// 会先将1000隐士转化为Person(1000)临时对象,再将该临时对象调用copy构造函数,完成
// 向pp1的赋值
Person pp1 = 1000;
// case2
// 直接调用了两个参数的构造函数
Person pp2(1, "qiumc");
Person pp3{1, "qiumc"};
// case3
// 产生了临时对象Person(1, "qiumc"),然后将该临时对象调用copy构造函数赋值给pp4
// 临时对象Person(1, "qiumc")是一个右值,而移动构造函数的参数类型是一个右值类型,所以,如果有移动构造函数,
// 这种形式将会调用移动构造函数,没有移动构造函数,将会调用copy构造函数
Person pp4 = Person(1, "qiumc");
// 同上
Person pp5 = Person{1, "qimmc"};
// case4
// 这种方式直接调用了两个参数的构造函数,而没有调用拷贝构造函数
// 如果有移动构造函数,也不会调用移动构造函数
// 这种形式也是一种单参数类型的隐式转化,如果两个参数的构造函数被声明为explicit形式,则这种定义将会报错
Person pp6 = {1, "qiumc"};
cout << pp1.id << " " << pp2.id << " " << pp3.id << " " << pp4.id << " " << pp5.id << " " << pp6.id << endl;
}
/**
* @brief
* 无参构造函数的几种写法
*/
void TestPersonInit() {
// 不能写成Person p1();因为这里无法和函数声明相区分开
// 同上case2
Person p2;
Person p3{};
// 同上case3,下面这两种,可以使用移动构造函数来减少拷贝
Person p4 = Person();
Person p5 = Person{};
// 同上case4
Person p6 = {};
}
/**
* @brief
* 一个参数的构造函数的简写方式
*/
void TestPersonSingleParamInit() {
// 如果没有类型符合的单参构造函数,这四种写法都会报错
// 下面这些都是发生了隐式转化
// 构造函数被声明为explicit时候,会禁止所有当前自定义的隐式类型转换,所以如果explicit修饰构造函数后,下面变量的定义都会报错
// explicit ,当有一个构造函数的定义和声明的时候,只能出现在构造函数声明处,不能出现在构造函数的定义处
Person p1 = 100; // id = 100
Person p2 = (200); // id = 200
Person p3 = (1, 2, 3, 4); // id = 4
Person p4 = {1}; //这种形式也是一种单参数类型的隐式转化,但是这种转换并没有产生临时对象后再调用copy构造函数
cout << p1.id << ":" << p2.id << ":" << p3.id << endl;
}
/**
* @brief
* 拷贝构造函数的几种写法
*/
void TestPersonCopy() {
// 调用构造函数
Person pp(1, "qiumc");
// 调用拷贝构造函数
Person pp1(pp);
// 调用拷贝构造函数
Person pp2{pp};
// 第二次调用:如果如果有移动构造函数先调用移动构造函数,否则调用copy构造函数
// 调用拷贝构造函数后,调用拷贝/移动构造函数
Person pp3 = Person(pp);
// 调用拷贝构造函数后,调用拷贝/移动构造函数
Person pp4 = Person{pp};
// 发生了隐式类型转换,但仅仅调用拷贝构造函数
Person pp5 = {pp};
}
/**
* @brief
* 注意整型数据初始化,和自定义类型初始化,基本上是可以类比的。
*/
int main(int argc, char const* argv[]) { TestPersonCopy(); }