当前位置: 首页 > news >正文

C++ 变量初始化方式总结 | 拷贝初始化 | 列表初始化 | 值初始化

1. 拷贝初始化

int a = 1;
std::string s = "hello";
  • 最经典、最普遍的写法

  • 类类型会调用构造函数进行“拷贝构造”(可能优化为直接构造)

  • 存在隐式类型转换风险

2. 直接初始化

int a(1);
std::string s("hello");
  • 使用括号直接初始化变量

  • 对类对象来说通常更高效

  • 构造函数如果加了 explicit,只能使用此方式

3. 列表初始化

示例:

int a{10};                 // 初始化为 10
std::string s{"hello"};    // 初始化字符串
std::vector<int> v{1, 2, 3}; // 初始化容器

列表初始化的几种形式

写法名称示例
T var{val};直接列表初始化int a{10};
T var = {val};拷贝列表初始化int b = {20};
T var{};值初始化(默认)int c{}; // 0

列表初始化的优点

1. 防止窄化转换

int a{3.14};  // ❌ 编译错误:不能将 double 隐式转换为 int
int b = 3.14; // ✅ 会自动截断为 3(但可能有隐患)

所以 {} 更安全,防止精度丢失

2. 支持类类型初始化

class Person {
public:Person(int age, std::string name) { ... }
};Person p1{18, "Tom"};  // 列表初始化成员变量
  • 简洁、清晰

  • 支持构造函数匹配

3. 可以初始化数组、容器等聚合类型

int arr[] = {1, 2, 3};                 // 数组
std::vector<int> vec{1, 2, 3};        // 容器
std::tuple<int, std::string>{1, "a"}; // 其他聚合结构

4. 原理:列表初始化本质调用的是 initializer_list 构造函数

当你使用花括号 {} 来初始化一个类对象时,编译器会尝试匹配下面这些可能的构造函数:

  1. 最优先:MyArray(std::initializer_list<T>)

  2. 然后尝试普通构造函数:MyArray(int, int)

所以,要让你的 MyArray<T> 支持:

MyArray<int> arr{1, 2, 3};

你必须提供:

MyArray(std::initializer_list<T> list)

示例:手写一个支持列表初始化的 MyArray 类模板

#include <iostream>
#include <initializer_list>template<typename T>
class MyArray {
private:T* pData;std::size_t m_Size;public:// 构造函数:支持 std::initializer_listMyArray(std::initializer_list<T> list): pData(new T[list.size()]),m_Size(list.size()) {std::size_t i = 0;for (const auto& item : list) {pData[i++] = item;}std::cout << "initializer_list 构造函数调用" << std::endl;}// 析构函数~MyArray() {delete[] pData;}// 打印函数void print() const {for (std::size_t i = 0; i < m_Size; ++i) {std::cout << pData[i] << " ";}std::cout << std::endl;}
};

  使用示例

int main() {MyArray<int> arr{10, 20, 30, 40};arr.print();  // 输出:10 20 30 40return 0;
}

解析:std::initializer_list<T> 是什么?

  • 它是一个 轻量容器,用于存储一系列值。

  • 实际上,它内部只是一个指向数组的指针 + 元素个数。

  • 提供 .begin().end() 迭代器,可以用于范围 for 循环。

std::initializer_list<int> list = {1, 2, 3};
for (int v : list) {std::cout << v << std::endl;
}

注意事项

项目说明
只能作为构造函数参数initializer_list 不能直接赋值,只能构造或拷贝
只能接受同一类型元素{1, 2, 3} 中必须都是同一种类型
列表初始化优先匹配 initializer_list 构造函数如果存在多个构造函数,花括号会优先调用这个

为了更强大,一般会重载多个构造函数:

MyArray(std::size_t size);                 // 有参构造
MyArray();                                 // 默认构造
MyArray(std::initializer_list<T> list);   // 列表初始化

这样你还可以支持:

MyArray<int> a1;               // 默认构造
MyArray<int> a2(10);           // 分配10个元素
MyArray<int> a3{1, 2, 3, 4};   // 列表初始化

    4. 拷贝列表初始化

    int a = {10};
    std::string s = {"abc"};
    
    • 使用 = + {} 的组合

    • 本质与列表初始化类似,禁止窄化

    5. 值初始化

    int a{};            // a 为 0
    std::string s{};    // s 是空字符串
    
    • 默认初始化为“零值”

    • 不再有“随机值”问题

    6. 默认初始化

    int a;  // ❌ 值未定义,可能是随机数
    
    • 局部变量如果未初始化,其值是“野值”

    • 对象成员变量如果没初始化,可能会调用默认构造函数(如果存在)

    数组、结构体、指针的初始化方式

    数组初始化

    int arr[3] = {1, 2};  // arr[2] 自动初始化为 0
    int arr[3]{};         // 所有元素初始化为 0
    

    指针初始化

    int* p1 = nullptr;  // 推荐写法(C++11)
    int* p2 = 0;        // 旧写法(仍合法,但不推荐)
    

     结构体初始化

    struct Point { int x, y; };
    Point p1 = {1, 2};  // C++98 风格
    Point p2{3, 4};     // C++11 风格,推荐
    

    类初始化与构造函数调用的关系

    class Person {
    public:explicit Person(int age) { ... }
    };Person p1 = 18;  // ❌ 错误:explicit 构造函数不能用拷贝初始化
    Person p2(18);   // ✅ 直接初始化
    Person p3{18};   // ✅ 列表初始化(推荐)
    

    explicit 构造函数:禁止隐式转换,因此无法使用 = 赋值初始化,只能用括号或花括号

    http://www.lryc.cn/news/611440.html

    相关文章:

  • 【C语言】动态内存管理详解
  • Kafka 的基本操作(1)
  • 国内办公安全平台新标杆:iOA一体化办公安全解决方案
  • 【基础】第八篇 Java 位运算符详解:从基础到实战应用
  • 【java】大数据insert的几种技术方案和优缺点
  • 一种基于机器学习的关键安全软件WCET分析方法概述与实际工作原理举例
  • 多传感器融合
  • 机器人权利:真实还是虚幻,机器人权利研究如何可能,道德权利与法律权利
  • nodejs 编程基础01-NPM包管理
  • 《计算机“十万个为什么”》之 面向对象 vs 面向过程:编程世界的积木与流水线
  • 【android bluetooth 协议分析 01】【HCI 层介绍 30】【hci_event和le_meta_event如何上报到btu层】
  • 零基础人工智能学习规划之路
  • 电路基础相关知识
  • HBM Basic(VCU128)
  • 翻译的本质:人工翻译vs机器翻译的核心差异与互补性
  • NumPy字符串与数学函数全解析:从基础到实战应用
  • 3. 为什么 0.1 + 0.2 != 0.3
  • ubuntu自动重启BUG排查指南
  • 前端遇到页面卡顿问题,如何排查和解决?
  • C语言:20250805学习(文件预处理)
  • 集成学习与随机森林:从原理到实践指南
  • 高通平台Wi-Fi Display学习-- 调试 Wi-Fi Display 问题
  • 【Git】实现使用SSH方式连接远程仓库时的免密操作
  • 17.8 ChatGLM3/CogVLM一键部署指南:32K长文本+多模态实战,零基础搞定企业级模型微调(附完整代码)
  • 机器学习算法系列专栏:决策树算法(初学者)
  • systemui 的启动流程是怎么样的?
  • VUE2 学习笔记 合集
  • 系统设计入门:成为更优秀的工程师
  • (ZipList入门笔记一)ZipList的节点介绍
  • 【面试场景题】日志去重与统计系统设计