条款26:尽可能延后定义式的出现时间
在看这个条款之前,我们先来看看如下代码:
std::string encryptPassword(const std::string& password){
using namespace std;
string encrypted;
if(pw.length()<miniLength){
throw logic_error("Password is too short");
}
...
return encrypted;
}
想象这种形式的代码可能有什么问题呀,哈哈,有很大问题呢?如果该函数执行到if语句时候抛出异常,你仍得付出encrypted的构造函数和析构函数,浪费资源,这时候我们可以考虑将其延后,直到确保需要它,代码如下:
std::string encryptPassword(const std::string& password){
using namespace std;
if(password.length()<MinimumPasswordLength){
throw logic_error("Password is too short!");
}
string encrypted;
...//必要的动作,但确保这些代码中不能抛出异常
return encrypted;
}
我们知道,我们对一个对象赋值,可以有两种方法:1)通过默认构造函数构造出一个对象,然后调用赋值运算符对其进行赋值;2)直接在构造时指定初值。那么那种比较好呢?因为第二种在构造时候直接赋初值,效率很高,因此我们常常使用第二种,代码如下:
第一种:
std::string encryptPassword(const std::string& password){
...
std::string encrypted;
encrypted=password;//先声明变量,然后赋值
encrypt(encrypted);
return encrypted;
}
第二种;
std::string encryptPassword(const std::string& password){
...
std::string encrypted(password);//调用copy构造函数,在定义时候直接赋初值
encrypt(encrypted);
return encrypted;
}
PS:如果在声明默认构造函数后,没有定义该类的copy assignmeng操作符号,只是顶一个copy constructor构造函数,那么“copy构造函数适用于第一次出现的变量,copy assignment运算符适用于第二次或者以上出现的变量”这条规则在这儿不适用,因为你没有定义copy assignment构造符,所以只能调用copy constructor了,代码如下:
#include <iostream>
#include <string>
using namespace std;
class A{
public:
A(int xx) :x(xx){
}
A(){
}
void show(){
cout << x << endl;
}
A(const A&a){
cout << "a的构造函数。。。" << endl;
this->x = a.x;
}
/*A& operator=(const A& a){
this->x = a.x;
return *this;
}*/
private:
int x;
};
int main(){
A a(10);
A a1 = a;
a1.show();
return 0;
}
运行结果:
同时,除了上述两种情况外,还可能有循环的情况,这是后我们就需要考虑如下两种情况那种比较好一些:
1)外部定义+内部赋值
Widget w;
for(int i=0;i<n;i++){
w=...;
...
}
2)内部定义+内部赋值
for(int i=0;i<n;i++){
Widget w(...);
...
}
这时候我们就需要考虑一下啦,如果Widget的构造+析构成本很大的话,尤其当n很大的时候,或者当代码效率高度敏感的部分,我们选用1)做法,否则选用2)做法,1)做法对w的作用域比2)做法的作用于范围更大一些。
总结:尽可能延后变量定义式出现的时间,这样可以增加程序的清晰度,并改善程序执行的效率。