c++11 之 统一初始化(Uniform Initalization)

一. 变量初始化

int a = 1;int b(2); 两种写法,无统一标准

c 复制代码
// 主函数:程序执行的起点(必须有且仅有一个)
int main() {
    // 基本类型:统一用 {},支持省略等号
    int a{1};       // 等价于 int a = 1;
    double b{3.14}; // 无隐式类型转换(如写 b{3} 没问题,但 b{3.14f} 也没问题,严格来说是窄化转换被禁止)

    std::cout << "Hello GCC! 这是C++主程序" << std::endl;  // 控制台输出内容
    return 0;  // 程序正常退出(返回0表示成功)
}

二. 数组初始化

int arr[] = {1,2,3};` 对于聚合对象有区别

c++ 复制代码
// main.cpp:C++ 主程序入口
#include <iostream>  // 包含输入输出流库(cout 所需)

struct teacher {
    int id;         // 成员1:编号
    const char* name; // 成员2:姓名
    int age;        // 成员3:年龄
};

// 主函数:程序执行的起点(必须有且仅有一个)
int main() {
    // 验证1:单个对象的聚合初始化(C++11+支持,C++03不支持)
    teacher t1 = {101, "Zhang San", 35}; // 等号可选
    teacher t2{102, "Li Si", 40};        // C++11+ 允许省略等号(列表初始化)

    // 验证2:数组的聚合初始化(直接用成员值,而非已创建对象)(C++11+支持,C++03不支持)
    teacher arr[] = {
        {103, "Wang Wu", 38},  // 直接初始化数组第1个元素
        {104, "Zhao Liu", 42}  // 直接初始化数组第2个元素
    };


    std::cout << "Hello GCC! 这是C++主程序" << std::endl;  // 控制台输出内容
    return 0;  // 程序正常退出(返回0表示成功)
}
  • g++ main.cpp -o test -std=c++03 方式编译会报错

  • g++ main.cpp -o test -std=c++11 方式编译不会报错

三. 容器初始化

vector<int> v; v.push_back(1); v.push_back(2); 繁琐,不能直接批量赋值;

c++ 复制代码
// C++98 代码
#include <vector>
using namespace std;

int main() {
    vector<int> v; // 空容器
    v.push_back(1); // 第1个元素
    v.push_back(2); // 第2个元素
    v.push_back(3); // 第3个元素
    // 若要初始化10个元素,需写10行push_back,极其冗余
    return 0;
}

C++98 甚至不支持 vector<int> v = {1,2,3}; 这种直观写法,唯一的「批量初始化」 workaround 是用数组临时中转,但更繁琐:

c++ 复制代码
// C++98 勉强实现批量初始化(不推荐)
int temp[] = {1,2,3};
vector<int> v(temp, temp + sizeof(temp)/sizeof(temp[0])); // 借助迭代器范围

在c++11标准下,支持以下方式:

cpp 复制代码
// C++11 代码
#include <vector>
#include <map>
#include <list>
using namespace std;

int main() {
    // 1. vector 直接批量初始化(像数组一样简洁)
    vector<int> v{1,2,3,4,5}; // 等价于 v = {1,2,3,4,5},支持等号可选
    vector<string> strs{"apple", "banana", "orange"}; // 字符串容器也支持

    // 2. 其他容器同样支持
    list<int> lst{10,20,30}; // 链表
    map<string, int> score{
        {"Zhang", 90},
        {"Li", 85},
        {"Wang", 95} // map 的键值对批量初始化,直观清晰
    };

    // 3. 嵌套容器初始化(复杂场景也支持)
    vector<vector<int>> matrix{
        {1,2,3},
        {4,5,6},
        {7,8,9} // 二维vector直接初始化,无需多层push_back
    };

    return 0;
}

代码可读性直接拉满,一眼就能看出容器的初始内容,彻底告别冗余的 push_back

C++11 容器的 {} 初始化会直接根据 initializer_list 中的元素个数,一次性分配足够的内存,避免了多次扩容和元素拷贝:

  • 比如 vector<int> v{1,2,3,4,5},容器会先计算出需要存储 5 个元素,直接分配能容纳 5 个 int 的内存,再把元素拷贝进去(仅一次拷贝);
  • 而 C++98 的 push_back 可能需要 2-3 次扩容(比如初始容量 1→2→4→8,最后容量 8,浪费空间且有多次拷贝)。

四. 窄化转换风险

double x = 3.14; int y = x;(double→int 丢失精度,C++98 仅警告,不报错);

c 复制代码
int main() {
    // 测试1:C++98 允许的窄化转换(C++11 {} 禁止)
    int a{3.14}; // 窄化转换:编译错误(C++11)

    // 测试2:显式转换后允许(C++11)
    int b = static_cast<int>(3.14); // 显式声明,编译通过

    cout << "b = " << b << endl;
    return 0;
}
  • g++ main.cpp -o test -std=c++03 编译只有警告,但是能编译通过
  • g++ main.cpp -o test -std=c++11 编译报错

五. 初始化歧义

vector<int> v(10);(10 个默认值 0)和 vector<int> v{10};(1 个元素 10),C++98 无区分方式

仅支持圆括号 () 初始化vector<int> v(10) 的行为和 C++11 一致(创建 10 个默认值为 0 的元素)

不支持花括号 {} 初始化vector<int> v{10} 在 C++98 中是 语法错误,编译器无法识别花括号作为初始化列表的语法。

c 复制代码
int main() {
    std::vector<int> v1(10);
    std::cout << "v1 使用 (10) 初始化:" << std::endl;
    std::cout << "  大小: " << v1.size() << std::endl;

    std::vector<int> v2{10};
    std::cout << "v2 使用 {10} 初始化:" << std::endl;
    std::cout << "  大小: " << v2.size() << std::endl;

    
    // C++98 中,圆括号 () 的行为和 C++11 一样
    // C++98 中,没有列表初始化语法,花括号 {} 不能这样用
    // std::vector<int> v98_2{10}; // 编译错误!C++98 不认识这种语法。

    return 0;
}
ini 复制代码
g++ main.cpp -std=c++03

使用c++03编译的时候,会有报错

ruby 复制代码
root@DFH-X5-243030:/mnt/d/linux_path/study# g++ main.cpp -std=c++03
main.cpp: In function 'int main()':
main.cpp:15:24: warning: extended initializer lists only available with '-std=c++11' or '-std=gnu++11' [-Wc++11-extensions]
   15 |     std::vector<int> v2{10};
      |                        ^
main.cpp:15:22: error: in C++98 'v2' must be initialized by constructor, not by '{...}'
   15 |     std::vector<int> v2{10};
      |                      ^~
root@DFH-X5-243030:/mnt/d/linux_path/study#

使用c++11编译正常,打印结果如下:

ruby 复制代码
root@DFH-X5-243030:/mnt/d/linux_path/study# g++ main.cpp -std=c++11
root@DFH-X5-243030:/mnt/d/linux_path/study# ll
total 32
drwxrwxrwx 1 gupan gupan  4096 Nov 21 11:13 ./
drwxrwxrwx 1 gupan gupan  4096 Nov 11 17:35 ../
-rwxrwxrwx 1 gupan gupan 25160 Nov 21 11:13 a.out*
-rwxrwxrwx 1 gupan gupan   803 Nov 21 11:13 main.cpp*
root@DFH-X5-243030:/mnt/d/linux_path/study# ./a.out
v1 使用 (10) 初始化:
  大小: 10
v2 使用 {10} 初始化:
  大小: 1
root@DFH-X5-243030:/mnt/d/linux_path/study#
相关推荐
艾莉丝努力练剑1 小时前
【C++:哈希表封装】用哈希表封装unordered_map和unordered_set
java·c++·stl·哈希算法·散列表·平衡二叉树·哈希
你好,赵志伟1 小时前
Reactor反应堆
网络·c++
y***54882 小时前
C++在游戏引擎中的开发
开发语言·c++·游戏引擎
AA陈超2 小时前
Lyra项目中的输入系统
c++·笔记·学习·游戏·ue5·lyra
铅笔小新z2 小时前
【C++】从理论到实践:类和对象完全指南(中)
开发语言·c++
千疑千寻~2 小时前
【C++】std::move与std::forward函数的区别
开发语言·c++
hansang_IR2 小时前
【记录】四道双指针
c++·算法·贪心·双指针
_OP_CHEN2 小时前
算法基础篇:(十二)基础算法之倍增思想:从快速幂到大数据运算优化
大数据·c++·算法·acm·算法竞赛·倍增思想
Murphy_lx2 小时前
C++ 条件变量
linux·开发语言·c++