当前位置:

首页 > 编程开发 > C++默认构造函数详解

C++默认构造函数详解

C++类中若未显式定义构造函数,编译器会生成隐式默认构造函数。默认构造函数指无需实参即可调用的构造函数,包括无参或全缺省参数形式。自动生成的构造函数对内置类型成员不做初始化,对自定义类型成员则调用其默认构造函数。

一、类的默认成员函数

当你定义一个看似“空”的类时,编译器并不会真的两手一摊——它会在背后默默为你准备一组特殊成员函数。在C++98标准下是6个,到了C++11又增加了几个新面孔。这些函数统称为**默认成员函数**,它们各自负责什么?看下表就清楚了: | 函数 | 作用 | |------|------| | 默认构造函数 | 初始化对象 | | 析构函数 | 清理对象资源 | | 拷贝构造函数 | 用已有对象初始化新对象 | | 赋值运算符重载 | 将已有对象赋值给另一对象 | | 移动构造函数(C++11) | 用临时对象“转移”资源 | | 移动赋值运算符(C++11) | 临时对象赋值 | 简单来说:只要你自己没主动声明这些函数,编译器就会自动生成一个“差不多能用”的默认版本。这听起来很方便,但实际用起来有不少坑——后面我们会一一拆解。

二、构造函数的基本概念

构造函数是类中一种特殊的成员函数,它在对象创建时自动被调用,专门用来初始化成员变量。它的规则其实很简洁: - 函数名必须和类名完全相同 - 没有返回值(连`void`都不用写) - 支持重载——你可以写多个参数不同的构造函数 - 对象创建那一刻自动执行,不需要手动调用 来看个直观的图(图注:构造函数调用流程示意图): ![C++默认构造函数详解](http://img.318050.com/uploads/20260605/17806259876a2232430188d695576990.webp) 基本概念就这些,但真正容易让人困惑的是“默认构造函数”到底指什么——下面我们细说。

三、默认构造函数的含义

所谓默认构造函数,就是**可以不传任何实参就能调用的构造函数**。它有两种来源: 1. **程序员自己定义的默认构造函数**,包括: - 无参构造函数(典型的`ClassName() {}`) - 全缺省参数的构造函数(比如`ClassName(int a = 0, int b = 0) {}`) 2. **编译器自动生成的隐式默认构造函数**——也就是程序员一个构造函数都没写时,编译器“代劳”的那个。 看两个例子就明白了: ```cpp class Student { public: // 无参构造函数 Student() { name = "无名"; age = 0; } private: string name; int age; }; class Point { public: // 全缺省参数的构造函数(也是默认构造函数) Point(int x = 0, int y = 0) : x(x), y(y) {} private: int x, y; }; ``` 注意:如果你同时定义了带参构造函数和全缺省构造函数,编译器会启动二义性判断——不过那是另一回事了。

四、编译器自动生成的默认构造函数

如果你一个构造函数都没写,编译器就会帮你生成一个隐式默认构造函数。比如: ```cpp class Dog { string name; int age; // 编译器自动生成 Dog() {} }; ``` 那么这个自动生成的构造函数到底干了什么?两个关键点: - **对于内置类型**(如`int`、`char`、指针等)**:什么都不做**——变量保持随机值(不同编译器的行为可能略有差异)。 - **对于自定义类型成员**:**调用它们各自的默认构造函数**。 来看一个能验证上述行为的例子: ```cpp #include using namespace std; class A { public: A() { cout << "A的构造函数" << endl; } }; class B { int x; // 内置类型,不会初始化(垃圾值) A a; // 类类型,会调用A的默认构造函数 }; int main() { B b; // 输出:A的构造函数(x保持随机) } ``` 这里有个容易踩的坑:**一旦你主动实现了任何一个构造函数,编译器就不再自动生成默认构造函数**。比如: ```cpp class Student { public: Student(string n) { name = n; } // 自定义构造函数 private: string name; }; int main() { Student s1("张三"); // 正确 // Student s2; // 错误!没有默认构造函数可用 } ``` 如果你既需要带参构造,又希望支持无参创建对象,那就必须自己手动提供一个默认构造函数。

五、默认构造函数的用途

**1. 定义对象而不初始化** 有些场景下需要先“空壳”对象,之后再赋值。比如一个数组包装类: ```cpp class Array { int* data; public: Array() { data = nullptr; } // 允许定义空数组对象 }; Array arr; // 调用默认构造 ``` **2. 作为容器元素的默认构造要求** STL容器(如`vector`)在扩容或创建元素时,经常需要元素的默认构造函数。如果你定义了一个没有默认构造的类,那么`vector v(10)`这种代码就会编译失败。 ```cpp vector v(10); // 需要Student有默认构造函数 ``` **3. 继承体系中基类的初始化** 派生类的构造函数会自动调用基类的默认构造函数(如果基类没有默认构造,派生类就必须显式调用基类的带参构造)。

六、什么时候需要自定义默认构造函数?

并不是所有类都需要手写默认构造。看看下面这个判断表就知道了: | 情况 | 是否需要自定义 | |------|----------------| | 类没有指针成员,且成员都有合理的默认值 | 不需要,编译器生成即可 | | 成员中需要分配资源(如动态内存) | 需要(在构造中分配并初始化) | | 需要给成员变量设置特定的初始值 | 需要 | | 类有自定义的带参构造,但仍需无参创建对象 | 需要 | 举个例子:如果你的类里有指针成员,编译器生成的默认构造只会留下未初始化的野指针,这通常不是你想要的结果: ```cpp class MyString { char* buf; public: // 自定义默认构造:给指针一个安全的初始值 MyString() { buf = new char[1]; buf[0] = '\0'; } }; ```

七、C++11 的改进:default 和 delete

C++11引入了两个非常有用的关键字,让你更精确地控制编译器的生成行为: - `= default`:显式要求编译器生成默认版本(哪怕你已经定义了其他构造函数) - `= delete`:禁止某个构造函数(或任何成员函数) ```cpp class Widget { public: Widget() = default; // 手动要求编译器生成默认构造 Widget(const Widget&) = delete; // 禁止拷贝构造 }; ``` 这比之前那种“要么不写,要么全写”的二元选择灵活多了。

八、一个完整的例子

最后用一个完整的程序把今天讲的内容串起来: ```cpp #include #include using namespace std; class Book { public: // 默认构造函数 Book() { title = "未命名"; price = 0.0; cout << "调用默认构造函数" << endl; } // 带参构造函数(不是默认构造) Book(string t, double p) : title(t), price(p) { cout << "调用带参构造函数" << endl; } void print() { cout << "书名:" << title << ",价格:" << price << endl; } private: string title; double price; }; int main() { Book b1; // 调用默认构造 Book b2("C++教程", 59.9); // 调用带参构造 b1.print(); b2.print(); return 0; } ``` 输出: ``` 调用默认构造函数 调用带参构造函数 书名:未命名,价格:0 书名:C++教程,价格:59.9 ``` 从这段输出可以清楚看到:不同的构造函数在不同场景下被调用,各自执行了不同的初始化逻辑。这就是我们使用默认构造函数的基础场景。掌握好它,后续学习移动语义、资源管理等内容时才会更加顺畅。
本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
作者最新文章
编程开发
相关文章 更多
C++构造函数类型:默认、拷贝与移动构造
C++构造函数类型:默认、拷贝与移动构造

默认构造函数、拷贝构造函数和移动构造函数是C++对象初始化的核心机制。默认构造函数在无参数时创建对象,若未定义任何构造函数,编译器会隐式生成,但不初始化内置类型成员;显式使用=default可保留默认构造,=delete可禁止。拷贝构造函数ClassName(constClassName&)用于通过现有对象创建新对象,执行成员逐个拷贝,对资源管理类需显式定义以实现深拷贝,避免浅拷贝导致的双重释放;若定义了析构函数、拷贝或移动操作之一,编译器不再生成隐式拷贝构造。移动构造函数ClassName(Cl

C++构造函数设计:默认、拷贝与移动实践
C++构造函数设计:默认、拷贝与移动实践

C++构造函数的设计关键在于正确管理类中的资源,特别是动态分配的内存,默认构造函数、拷贝构造函数和移动构造函数分别负责对象的初始化、复制和资源转移。1.默认构造函数用于初始化对象,当类包含需手动管理的资源(如指针)时应自定义,确保资源正确初始化;2.拷贝构造函数应执行深拷贝以避免多个对象共享同一资源导致悬挂指针;3.移动构造函数通过转移资源所有权提升性能,避免不必要的复制;4.若类不管理资源,应遵循RuleofZero使用编译器生成的默认函数;5.为避免资源泄漏,应在构造时分配、析构时释放资源,使用智能指

查看更多
精品专题 更多
装机必备
装机必备

正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

Windows
Windows

正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

PDF教程
PDF教程

正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

Mac软件 更多
Adobe Acrobat Pro macOS版
Adobe Acrobat Pro macOS版
Mac

Adobe Acrobat Pro 是面向办公、法务、财务、教育及出版用户的专业PDF处理软件,可在Mac上创建、编辑、转换、合并和保护文档,并提供OCR文字识别、表单、批注、内容比较、敏感信息遮盖及电子签名功能。

Blender
Blender
Windows、macOS 和 Linux

Blender 是一款免费开源、跨平台的专业 3D 创作软件,集建模、动画、渲染、视频编辑与视觉合成等功能于一体,广泛应用于影视动画、游戏设计和建筑可视化等领域。软件支持 Cycles 物理渲染器与 Eevee 实时渲染引擎,并提供多边形建模、骨骼绑定、物理模拟等专业工具。Blender 兼容 Windows、macOS 和 Linux 系统,安装包轻巧、运行流畅,依托活跃的全球开发者社区持续更新,是从初学者到专业创作者都值得选择的正版 3D 创作工具。

Shapr3D macOS版
Shapr3D macOS版
Mac

Shapr3D是一款面向工业设计、机械工程、建筑概念和三维打印工作流的CAD软件。Mac版采用Parasolid建模内核,支持草图约束、实体建模、工程图、可视化渲染及常见CAD格式交换,并可通过账户在多台设备之间同步项目。

WINDOWS 更多
AutoCAD Windows版
AutoCAD Windows版
Windows

AutoCAD 是 Autodesk 推出的专业计算机辅助设计软件,Windows 版支持精确二维绘图、三维实体与曲面建模、图纸标注、布局发布和任务自动化,并包含多套行业专业化工具组合,适用于建筑、机械、电气、工程建设及制造设计人员。

Adobe Acrobat Pro Windows版
Adobe Acrobat Pro Windows版
Windows

Adobe Acrobat Pro 是面向专业 PDF 工作的综合解决方案,可在 Windows 中创建、编辑、转换、比较、整理和保护文档,并支持表单、电子签名、扫描件文字识别及敏感信息永久遮盖。订阅还包含网页、移动服务和云端协作能力,

Blender
Blender
Windows、macOS 和 Linux

Blender 是一款免费开源、跨平台的专业 3D 创作软件,集建模、动画、渲染、视频编辑与视觉合成等功能于一体,广泛应用于影视动画、游戏设计和建筑可视化等领域。软件支持 Cycles 物理渲染器与 Eevee 实时渲染引擎,并提供多边形建模、骨骼绑定、物理模拟等专业工具。Blender 兼容 Windows、macOS 和 Linux 系统,安装包轻巧、运行流畅,依托活跃的全球开发者社区持续更新,是从初学者到专业创作者都值得选择的正版 3D 创作工具。