news 2026/5/2 18:58:24

C++ 中的初始化

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C++ 中的初始化

文章目录

    • 一、初始化简介
    • 二、C++ 中的初始化
      • 2.1、内置类型初始化
      • 2.2、STL 容器类型初始化
      • 2.3、new 的初始化
      • 24、结构体初始化
      • 2.5、类的初始化
    • 三、参考资料

一、初始化简介

  • C++ 中的两种数据类型:内置类型和类类型

    • 内置类型char、bool、short、int、float、double、指针等 C++ 语言支持的最基础的数据类型
    • 类类型:标准库以及我们自己定义的各种类、结构体、模板类等,如MyClass、MyStruct、std::vector<T>、std::string、std::unique_ptr<T>..
  • 初始化和赋值的区别:

    • 初始化的概念创建变量(为特定类型的变量申请存储空间)的同时赋予初始值;如果是类类型,将调用类的构造函数
    • 赋值的概念已创建的变量的值用另一个值替代,不创建新的变量;如果是类类型,将调用类的赋值运算符operator=()
    inta=1;// 初始化a=2;// 赋值MyClass obj1;// 初始化,调用 MyClass() 构造函数MyClass obj2{42,"hello"};// 初始化,调用 MyClass(int, string) 构造函数obj1=obj2;// 赋值,调用 operator=(const MyClass&)
  • 显示初始化、隐式初始化与未初始化:

    • 显示初始化和隐式初始化:无论何时只要类的对象被创建就会执行构造函数,通过显式调用构造函数进行初始化被称为显式初始化,否则叫做隐式初始化
    • 未初始化:未被用户指定初始值,那么这些变量会被执行默认初始化,默认值取决于变量类型和定义变量的位置
      • 内置类型:全局(包括定义在任何函数之外、命名空间之内的)变量或局部静态变量初始化为 0(这种情况也叫值初始化);局部非静态变量或类成员未定义(未初始化)
      • 类类型:由类的默认(无参)构造决定
    #include<iostream>// Cat 提供两个构造函数classCat{public:intage;Cat()=default;// ✅ = default: 显式请求编译器生成默认构造函数explicitCat(inti):age(i){}};intmain(){Cat cat1;// 隐式初始化: 调用默认构造函数Catcat2(10);// 隐式初始化: 调用一个形参的构造函数Cat cat3=Cat();// 显式初始化: 调用默认构造函数Cat cat31{};// 优选:列表初始化Cat cat4=Cat(5);// 显式初始化: 调用一个形参的构造函数Cat cat41{5};// 优选:列表初始化// 构造函数还可以搭配 new 一起使用, 用于在堆上分配内存Cat*cat5=newCat();Cat*cat51=newCat{};// 优选:列表初始化Cat*cat6=newCat(3);Cat*cat61=newCat{3};// 优选:列表初始化return0;}
  • 列表初始化(使用花括号 {} 形式的初始化):C++11 新标准将列表初始化应用于所有对象的初始化,但一般有如下编程习惯

    • 内置类型习惯于用等号 = 初始化(C/C++ 通用)
    • 类型习惯用构造函数圆括号()调用默认初始化或者花括号{} 优选零初始化显式初始化
    • vector、map 和 set等容器类习惯用列表{}初始化
    // 1、列表初始化可以防止窄化转换longdoubleld=3.1415;inta{ld};// 无法编译,转换存在信息丢失的风险intb={ld};// 无法编译,转换存在信息丢失的风险inta{static_cast<int>(ld)};// OK,有意转换intc(ld);// 可以编译,但信息丢失intd=ld;// 可以编译,但信息丢失

二、C++ 中的初始化

  • 堆内存使用动态大小、跨函数使用或者有可能会使用较大的结构体(离开作用域时不会自动释放),使用堆内存是更合适的选择(比如
  • 栈内存使用:如果结构体较小且作用域明确(当变量超出作用域时,内存自动回收),使用栈内存定义结构体变量会更简单且高效(比如简单结构体,使用{}初始化即可)

2.1、内置类型初始化

  • 使用等号(=)初始化一个类变量执行的是拷贝初始化,编译器会把等号右侧的初始值拷贝到新创建的对象中去,不使用等号则执行的是直接初始化
inti1=0;// (1) 拷贝初始化,C/C++ 中通用,**首选**inti2={0};// (2) 拷贝初始化inti3{0};// (3) 直接初始化inti4(0);// (4) 直接初始化inti5;// (5)未初始化,如果是全局变量值为 0;局部变量为随机值

2.2、STL 容器类型初始化

// 1、普通容器变量初始化std::string s1="hello";// (1) 拷贝初始化std::string s2={"hello"};// (2) 拷贝初始化,它不可用于构造函数初始值列表,而(3)可以std::string s3{"hello"};// (3) 列表直接初始化,**首选**,容器类习惯用列表初始化std::strings4("hello");// (4) 构造直接初始化std::string s5;// (5)调用默认构造函数,值为空字符串,std::basic_string<char>();std::string s6{};// (6)调用默认构造函数,值为空字符串,std::basic_string<char>{};// 2、数组容器变量初始化// vu32InputNum1 = std::vector<int, std::allocator<int> >(2, std::allocator<int>());std::vector<int>vu32InputNum1(2);// 2 个 int,初始化为 0// u32InputNum2 = std::vector<int, std::allocator<int> >();std::vector<int>vu32InputNum2;// 调用默认构造函数,被默认初始化为空的 std::vector,初始值是一个空容器,不包含任何元素std::vector<int>vu32InputNum3{8,9};// 2 个 int,初始化为 8, 9// vsInputNames1 = std::vector<std::basic_string<char>, std::allocator<std::basic_string<char> > >(2, std::allocator<std::basic_string<char> >());std::vector<std::string>vsInputNames1(2);// 2 个 string,初始化为 ""// vsInputNames2 = std::vector<std::basic_string<char>, std::allocator<std::basic_string<char> > >();std::vector<std::string>vsInputNames2;// 调用默认构造函数,被默认初始化为空的 std::vector,初始值是一个空容器,不包含任何元素std::vector<std::string>vsInputNames3{"hello","world"};// 2 个 string,初始化为 "hello", "world"

2.3、new 的初始化

// 对于类类型,有无括号没区别string*ps1=newstring;// 默认初始化为空 stringstring*ps2=newstring();// 值初始化为空 stringstring*ps3=newstring{};// 值初始化为空 string, **首选**// 对于内置类型,有括号进行值初始化,没有括号的值未定义!int*pi1=newint;// 默认初始化,*pi1 值未定义!int*pi2=newint();// 值初始化,*pi2 为 0int*pi3=newint{};// 值初始化,*pi3 为 8int*pia1=newint[3];// 3个默认初始化的int: 值未定义int*pia2=newint[3]();// 3个值初始化的int: 值都为0,需区分 () 是调用还是初始化,不推荐/****** 重要 **首选** *******/int*pia3=newint[3]{};// 3个值初始化的int: 值都为0,用于开辟一块内存并初始化为 0;类似 calloc,不用 memset 了constint*pci1=newconstint(1024);// 分配并初始化一个 const intconstint*pci2=newconstint{1024};// 分配并初始化一个 const int

24、结构体初始化

// 重要:结构体类型使用列表初始化分配内存,可避免未初始化的成员变量带来的潜在问题typedefstructtagTAlgTensorHandle{ints32InputNum;intanInputWidth[2];intanInputHeight[2];std::string sInputName;std::vector<std::string>vsBrand;// 用于保存 brand 文件中的内容std::vector<std::string>vsBrand2Type;// 用于保存 brand 映射到 Type 文件中的内容void*pvDetectInGpuBuffer;// 模型输入,按照检测模型的输入大小分配void*pbyInputDataGpu;// 传入大图+ROI时,放置抠出小图的缓存}TAlgTensorHandle;// 可以默认初始值初始化一部分成员变量typedefstructtagTAlgTensorHandle{ints32InputNum{8};intanInputWidth[2]{112,112};intanInputHeight[2]{224,224};std::string sInputName;std::vector<std::string>vsBrand;// 用于保存 brand 文件中的内容std::vector<std::string>vsBrand2Type;// 用于保存 brand 映射到 Type 文件中的内容void*pvDetectInGpuBuffer;// 模型输入,按照检测模型的输入大小分配void*pbyInputDataGpu;// 传入大图+ROI时,放置抠出小图的缓存}TAlgTensorHandle;// 1、普通初始化:成员变量未定义TAlgTensorHandle ptTensorContext1;// 2、列表初始化:成员变量初始化为 0,nullptr 或空/********** 对于结构体类型优先使用此方式(不需要开辟内存的时候)进行初始化 *****************/TAlgTensorHandle ptTensorContext2{};// 3、开辟内存:将分配内存并创建一个 TAlgTensorHandle 对象,但不会对对象进行任何初始化。对象的成员变量将保持未定义的状态TAlgTensorHandle*ptTensorContext1=newTAlgTensorHandle;// 4、开辟内存将分配内存并创建一个 TAlgTensorHandle 对象,同时将所有成员变量初始化为其默认值。// 对于基本类型(如 int),它们会被初始化为 0;对于 std::string 和 std::vector,它们会被初始化为空/********** 对于结构体类型优先使用此方式(或者 C 语言 calloc 的方式)进行初始化 *****************/TAlgTensorHandle*ptTensorContext2=newTAlgTensorHandle{};printf("sizeof handle is %d %d\n",sizeof(*ptTensorContext2),sizeof(TAlgTensorHandle));

2.5、类的初始化

  • 类成员有两种初始化方式:类内初始值(成员初始化器,in-class member initializer)以及构造函数初始值列表(constructor initialize list

    • 尽量不要在构造函数体内部初始化数据成员,因为只有当类的所有成员初始化完成之后才开始执行构造函数体,此时并不是真正意义上的初始化,而是重新赋值
    • 引用成员const 成员只能通过类内初始值或者构造函数初始值列表初始化,而不能在构造函数体内部“初始化”
    • 注意
      • 对于内置类型的数据成员,如果没有对其进行显式初始化,其值未定义
      • 类的数据成员初始化顺序和构造函数初始化列表中的顺序无关,而是由成员在类中声明的顺序决定
  • 类内初始值/成员初始化器

    • 在类中声明类的(非静态)数据成员同时提供初始值,初始值可以是字面值、表达式甚至是函数调用
    • 形式上可以用等号或者花括号,但是不能用圆括号,C++11 之后首选的初始化类成员方式
    classSalesData{unsignedunitsSold=0;doublerevenue{0.0};std::string bookNo{"hello"};shared_ptr<int>sp={make_shared<int>(5)};};
  • 构造函数初始值列表

    • 如果需要根据传入构造函数的参数来初始化类成员,可以使用构造函数初始值列表
    • 构造函数初始值列表的形式是在构造函数的形参列表之后,使用冒号分隔,接着是成员名字,然后使用圆括号或花括号来包裹初始化的表达式,多个成员之间通过逗号分隔
classSalesData{public:SalesData(conststd::string&s):bookNo(s){}SalesData(conststd::string&s,unsignedn,doublep):bookNo(s),unitsSold(n),revenue(p*n){}};
  • 类内初始值和构造函数初始化列表同时使用:一部分成员变量使用类内初始默认值,一部分成员变量通过传参使用列表初始化
classKNN{public:KNN(constchar*name):sInputName(name){};// 构造函数public:ints32InputNum;ints32OutPutNum{1};intanInputWidth[2]{112,112};intanInputHeight[2]{224,224};std::string sInputName;void*pvPltParamHandle;char*u8Algname;private:ints32Modelsize;std::string key;};// 1、这种方式初始化未构造的参数,可能是未知的KNN pcAlgHandle1{"det"};// KNN pcAlgHandle1("det");// 2、这种方式初始化,成员变量一般会初始化为 0 或 nullptr 等KNN*pcAlgHandle2=newKNN{"cls"};// KNN *pcAlgHandle2 = new KNN("cls");// 除了需要外部传入的参数外,其它参数可以先使用默认初始化参数(或者不初始化),后面再赋值改变(一定要做)classKNN{public:KNN(constchar*name):sInputName(name){};// 构造函数public:ints32InputNum{1};ints32OutPutNum{1};intanInputWidth[2]{112,112};intanInputHeight[2]{224,224};std::string sInputName{"input"};void*pvPltParamHandle;char*u8Algname;private:ints32Modelsize{0};std::string key;};

三、参考资料

1、一文总结现代 C++ 中的初始化
2、一文讲通 C++ 所有初始化方法
3、探索C++中的“{}初始化”:优雅与高效的结合
4、C++中的初始化列表
5、五花八门的C++初始化规则
6、https://cppinsights.io

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/2 18:52:47

E7Helper:第七史诗自动化助手,解放你的游戏时间

E7Helper&#xff1a;第七史诗自动化助手&#xff0c;解放你的游戏时间 【免费下载链接】e7Helper 【Epic Seven Auto Bot】第七史诗多功能覆盖脚本(刷书签&#x1f343;&#xff0c;挂讨伐、后记、祭坛✌️&#xff0c;挂JJC等&#x1f4db;&#xff0c;多服务器支持&#x1f…

作者头像 李华
网站建设 2026/5/2 18:51:27

ARM处理器内存访问优化与字节序控制详解

1. ARM处理器中的内存访问优化机制在嵌入式系统开发中&#xff0c;内存访问效率直接影响整体性能表现。ARM架构通过一系列精妙的设计&#xff0c;为开发者提供了灵活的内存访问控制能力&#xff0c;特别是在处理未对齐数据和混合字节序场景时表现出色。1.1 未对齐数据访问支持未…

作者头像 李华
网站建设 2026/5/2 18:51:20

ElaWidgetTools与原生QT组件对比:为什么选择现代化UI框架

ElaWidgetTools与原生QT组件对比&#xff1a;为什么选择现代化UI框架 【免费下载链接】ElaWidgetTools Fluent-UI For QT-Widget 项目地址: https://gitcode.com/gh_mirrors/el/ElaWidgetTools ElaWidgetTools是一个专为QT-Widget打造的Fluent-UI框架&#xff0c;它通过…

作者头像 李华
网站建设 2026/5/2 18:51:19

长期使用Taotoken服务对业务API调用稳定性的整体观感

长期使用Taotoken服务对业务API调用稳定性的整体观感 1. 服务可用性观察 在持续使用Taotoken服务的过程中&#xff0c;我们注意到其API端点保持了较高的可用性。通过内部监控系统记录的数据显示&#xff0c;过去六个月的正常服务时间占比达到了行业标准水平。服务中断的情况极…

作者头像 李华
网站建设 2026/5/2 18:49:29

Nucleus Co-Op:5分钟实现PC游戏本地分屏的终极指南

Nucleus Co-Op&#xff1a;5分钟实现PC游戏本地分屏的终极指南 【免费下载链接】nucleuscoop Starts multiple instances of a game for split-screen multiplayer gaming! 项目地址: https://gitcode.com/gh_mirrors/nu/nucleuscoop 你是否曾想过&#xff0c;那些只支持…

作者头像 李华