最近在看Effective C++,结合自己的工作实践做点笔记,一来方便自己日后查看,二来鞭策自己不断学习。
1.为需要动态分配内存的类声明一个拷贝构造函数和一个赋值操作符
class String
{
public:
String(const String&); //拷贝构造函数
String& operator=(const String&);//赋值操作符=
private:
std:: string str;
};
String::String(const String& str)
{
this->str = str.str;
}
String& String:: operator=(const String& str)
{
this->str = str.str;
return *this;
}
2.尽量使用参数初始化列表对常数据成员进行初始化,而不要在构造函数里赋值,这样做的原因主要有两个:
- 带const和引用(&)的数据成员只能使用参数初始化列表进行初始化
class Int
{
public:
Int(int a, int b) :_a(a), _b(b) {} //正确 参数初始化列表
Int(int a, int b) //错误 带参的构造函数
{
_a = a;
_b = b;
}
private:
const int _a;
int& _b;
};
- 对于类中含有子类的对象,采用参数初始化列表方式效率更高
我们看下面一段代码段1:
class A
{
public:
A()
{
cout << "调用类A的默认构造函数" << endl;
}
};
class B
{
public:
B(const A a):_a(a)//初始化列表方式
{
cout << "调用类B参数初始化列表" << endl;
}
private:
A _a;
};
int main()
{
A a;
B b(a);
system("pause");
}
输出的结果为:
调用类A的默认构造函数
调用类B参数初始化列表
再看代码段2:
class A
{
public:
A()
{
cout << "调用类A的默认构造函数" << endl;
}
};
class B
{
public:
B(const A a) //构造函数方式
{
cout << "调用类B的构造函数" << endl;
}
private:
A _a;
};
int main()
{
A a;
B b(a);
system("pause");
}
输出的结果为:
调用类A的默认构造函数
调用类A的默认构造函数
调用类B的构造函数
从代码1和代码2的结果来看,采用构造函数初始化数据成员的方式多调用了一次类A的构造函数。
所以可以总结出:当类的数据成员为类对象时,采用构造函数初始化方式比采用参数初始化列表的方式会多调用一次数据成员对象的构造函数。
上一个例子的变形:
class A
{
public:
A() //默认构造函数
{
cout << "调用类A的默认构造函数" << endl;
}
A(const A& a) //拷贝构造函数
{
this->_aa = a._aa;
cout << "调用类A的拷贝构造函数" << endl;
}
A& operator=(const A& a) //赋值运算符
{
this->_aa = a._aa;
cout << "调用类A的赋值操作符" << endl;
return *this;
}
private:
int _aa = 0;
};
class B
{
public:
//B(const A& a):_a(a) //初始化列表方式
//{
// cout << "调用类B的参数初始化列表" << endl;
//}
B(const A& a) //构造函数方式
{
_a = a;
cout << "调用类B的构造函数" << endl;
}
private:
A _a;
};
int main()
{
A a;
B b(a);
system("pause");
}
结果:采用构造函数比采用初始化列表方式多调用一次A对象的默认构造函数