当前位置: 首页 > 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.xdnf.cn/news/1245673.html

    相关文章:

  • YooAsset源码阅读-Downloader篇
  • 本地使用uv管理的python项目怎么部署到服务器?
  • 攻击实验(ARP欺骗、MAC攻击、报文洪水攻击、DNS欺骗)
  • Laravel The requested URL /hellowzy was not found on this server. 404 问题的解决
  • 2025年渗透测试面试题总结-01(题目+回答)
  • 《Node.js与 Elasticsearch的全文搜索架构解析》
  • 如何用分布式架构视角理解宇宙稳定性?从精细调参到微服务的类比思考
  • 【C++】模板深入进阶
  • 检索召回率优化探究四:基于LangChain0.3集成Milvu2.5向量数据库构建的智能问答系统
  • Sklearn 机器学习 数据聚类 层次聚类的两个重要属性
  • 编码器模型和解码器模型解析
  • GPT-5的诞生之痛:AI帝国的现实危机
  • LLM开发——语言模型会根据你的提问方式来改变答案
  • arp攻击(ettercap 版本0.8.3.1)
  • Physics Simulation - UE中Projectile相关事项
  • tensorRT配合triton部署模型
  • HTML 如何转 Markdown
  • 【Redis】string常用命令
  • 417页PDF | 2025年“人工智能+”行业标杆案例荟萃
  • 三款好用的PDF阅读器
  • 深入理解 Android SO 导出符号:机制与安全优化
  • Python高级编程与实践:Python高级数据结构与编程技巧
  • 后量子时代已至?中国量子加密技术突破与网络安全新基建
  • 前端1.0
  • AIDL学习
  • 云计算一阶段Ⅱ——11. Linux 防火墙管理
  • 国产大模型平替方案:Spring Boot通义千问API集成指南
  • 【实时Linux实战系列】实时视频监控系统的开发
  • android开发 更改系统默认时区和默认语言
  • 笔试——Day29