C++编程注意事项——构造函数
C++ 编程注意事项 —— 构造函数
摘要
构造函数使用explicit
阻止隐式类型转换
区分拷贝构造函数和赋值运算符的不同
使用引用传递,避免值传递
构造函数
对于自定义的类型,使用explicit
阻止执行隐式类型初始化
对于用户自定义的类型,初始化由构造函数执行。将构造函数声明为explicit
可以阻止隐式类型转换。被声明为explicit
的构造函数通常比non-explicit
的构造函数更好,除非有充分的理由,否则所有的构造函数都应该声明为explicit
在显式类型转换使得程序员真的知道自己在做什么,清楚的知道调用了哪个构造函数,如果使用隐式构造函数,程序员可能并不清楚发生了类型转换,即使知道发生了类型转换,在找出实际执行构造函数执行的类型转换也需要花费一定的时间,而这很可能导致发生与预期不符的行为。
拷贝构造函数与赋值运算符
拷贝构造函数用来通过一个已有的同类型对象初始化一个新的对象
赋值运算符则是从另一个同类型对象中拷贝其值到本身
两者最大的区别在于,拷贝构造函数会创建一个新的对象,而赋值运算符并没有创建新的对象。
通过判断是否有新的对象被创建,可以区分调用哪个函数
class A{
public :
A(); //默认构造函数
A(const A& a); //拷贝构造函数
A& operator=(const A& a); //赋值运算符
};
A a1; //调用默认构造函数
A a2(a1); //调用拷贝构造函数
a1 = a2; //调用赋值运算符, 没有新的对象创建
A a3 = a1; //调用拷贝构造函数,新的对象a3被创建
可以通过在构造函数中输出信息来跟踪函数的调用情况:
class TestA{
public:
TestA();
TestA(const TestA& a);
TestA& operator=(const TestA& a);
};
TestA::TestA(){
cout << "run default construct;" << endl;
}
TestA::TestA(const TestA& a){
cout << "run copy construct;" << endl;
}
TestA& TestA::operator=(const TestA& a){
cout << "run '=';" << endl;
return *this;
}
int main(int, char**) {
TestA a1;
TestA a2(a1);
a1 = a2;
TestA a3 = a1;
return 0;
}
运行结果:
当以值传递的方式传递参数时,通过调用拷贝构造函数创建一个新的对象,因此拷贝构造函数被调用是一个很重要的函数。同时,在进行参数传递时也应该优先使用引用传递,避免创建新的对象。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通