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

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

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 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 vec{1, 2, 3};        // 容器
std::tuple{1, "a"}; // 其他聚合结构

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

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

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

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

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

MyArray arr{1, 2, 3};

你必须提供:

MyArray(std::initializer_list list)

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

#include
#include
template
class MyArray {
private:
T* pData;
std::size_t m_Size;
public:
// 构造函数:支持 std::initializer_list
MyArray(std::initializer_list 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 arr{10, 20, 30, 40};
arr.print();  // 输出:10 20 30 40
return 0;
}

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

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

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

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

std::initializer_list 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 list);   // 列表初始化

这样你还可以支持:

MyArray a1;               // 默认构造
MyArray a2(10);           // 分配10个元素
MyArray 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.sczhlp.com/news/6892/

    相关文章:

  • MySQL数据库二进制安装
  • 河南萌新联赛2025第(四)场:L(数论+素数筛)
  • 旋转锉的形状和用途
  • Golang笔记之Redis
  • 2025.8.06打卡
  • 【图论题解】方向迷宫 + 魔法路径判定:BFS 与 0-1 BFS 双解法详解
  • 软工8.6
  • 练习cf1920A. Satisfying Constraints
  • 广度优先搜索算法2
  • 【自学嵌入式:51单片机】红外遥控控制电机调速
  • Android Camera性能分析 – 通过Perfetto的PivotTable查看调用栈
  • 河南萌新联赛2025第(四)A
  • 2025 暑假集训 Day3
  • Linux 下查看超大文件(比如大日志) - Higurashi
  • Day36
  • Windows OpenGL 学习一(OpenGL 环境搭建)
  • 完整教程:2025年信创政策解读:如何应对国产化替代挑战?(附禅道/飞书多维表格/华为云DevCloud实战指南)
  • 18
  • 2.变量于应用
  • OI集训 Day21
  • STL的五大组件
  • 完整教程:吴恩达【prompt提示词工程】学习笔记
  • ArKTS: McPieChart
  • 2025.8.6总结 - A
  • 【fuse】struct fuse_lowlevel_ops解析-①
  • Policy Gradient原理和Python实现
  • 记一些oi啸寄巧
  • 25.8.6模拟赛
  • 考前建议
  • RS232与RS485通信协议深度对比