5、C++ 直接初始化和拷贝初始化
首先我们介绍直接初始化:编译器使用普通的函数匹配来选择与我们提供的参数最匹配的构造函数。文字描述可能会让你们云里雾里,那我们直接看代码:
1 2 3 4 5 6 7 | //先设计这样的一个类 class A{ public : A(){ cout << "A()" << endl; } A( int a){ cout << "A(int a)" << endl; } A( const A&){ cout << "A(const A&)" << endl; } }; |
1 2 | A a1(10); //直接初始化 A a2(a1); //直接初始化 |
结果为:
1 2 | A( int a) A( const A&) |
通过上述的例子,我们可以发现直接初始化其实就是根据传入的参数选择最匹配的构造函数来进行初始化。但是其中有一个误区需要指出:直接初始化有可能调用拷贝构造函数!!!不能因为直接初始化不是拷贝初始化,就想当然认为其不可能调用拷贝构造函数。
接下来,让我们再看看拷贝初始化。
1 2 3 | A a3 = a2; //拷贝初始化1 A a4 = 2; //拷贝初始化2 A a5 = A(3); //拷贝初始化3 |
结果为:
1 2 3 | A( const A&) A( int a) A( int a) |
上面介绍了在用=定义变量时发生的拷贝初始化,让我们仔细地来分析一下:
-
第1种情况:很好理解,是用a2去初始化a3,其实是
A a3(a2);
所以本次拷贝初始化是用了拷贝构造函数。 - 第2种情况:其实是相当于进行了两步:
-
A a4 = A(2);
这一步称之为隐式类型转化。A a4(A(2));
其实也是调用了拷贝构造函数。- 但需要注意的是:有的编译器会做一定的优化,即在vs2013环境下,会将该种情况直接变为
A a4(2);
- 第3种情况:其实就是
A a5(A(3));
同样在vs2013环境下会被优化为A a5(3);
拷贝构造初始除了用等号定义的情况,还有以下几种情况:
- 将一个对象作为实参传递给一个非引用类型的形参
void test(A a);
- 从一个返回类型为非引用类型的函数返回一个对象
return A test();
- 用花括号列表初始化一个数组中的元素或一个聚合类中的成员
string str[2]{"lll","ttt"};
某些类类型还会对他们所分配的对象使用拷贝初始化。如vector调用其insert或push成员。
参考资料:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!