C++(11后才有的特性)中通用初始化语法(universal initialization)的使用用法

it2025-08-09  8

universal initialization语法使得C++对变量对象的定义和初始化与C相比发生了明显的变化,更加方便与灵活。

如下代码所示:

--------cpp--------- int(1); int x(1); int{1}; int x3{2}; int x1[5]{1,2,3,4,5}; auto *p = new int[3]{1, 2};

这些语法在c语言中都是不成立的,但是再c++中都是可以的。

用()和{}等价于在C中的=号操作;

()是给基本类型变量用来初始化,{}是用来给自定义或官方的类(也是一种类型,不过不是基本类型)的对象初始化,{}包含了(),可以用()初始化的地方都可以用{}代替,但是{}不能用()代替。

格式:基本类型() 就可以表示申请了一个基本类型大小的内存,不用向C中那样必须要一个变量名,如下:

--------cpp--------- int(); //没有变量名,就向内存中申请了一块空间,没有初始化 int(1); //没有变量名,就向内存中申请了一块空间,初始化为1 int x(1); //也可以用变量名向内存中申请一块空间,初始化为1 int{1}; int x3{2};

格式:类名 {} 表示申请了一个类大小的内存(这里的类就相当于自定义的类型),与c中相似的语法就是结构体

如下代码: 首先定义了一个point类

#include <iostream> #include <string> #include<vector> using namespace std; struct point { int x; int y; point() = default; point(int z) : x{z}, y(z){ cout << "initial construct\n"; }; point(point &p) { cout << "copy construct\n"; } };

使用代码:

point ();//没有对象名,申请了一个point类大小的内存,调用了缺省构造函数初始化,一般 point p(); //有对象名,申请了一个point类大小的内存,调用了缺省构造函数初始化 point {}; point p4{}; point {4};//没有对象名,申请了一个point类大小的内存,调用了参数构造函数point(int z)初始化 point p6{4};//有对象名,申请了一个point类大小的内存,调用了参数构造函数point(int z)初始化 auto *p2 = new point[3]{1, 2}; point[3]{1, 2};//申请数组这种形式是错的,必须加上数组名,上面用new的也可以

point p6{4,2};使用这种形式初始化,如果类point中什么构造函数都没有,则该初始化直接对公共区域的成员变量赋值

struct point { int x; int y; //这里什么构造函数都没有,复制,析构都没 }; point p6{42};//4赋给x,2赋给y

如果point类中有复制构造函数,则是调用复制构造函数来赋值(这个时候就相当于将大括号变为小括号,与调用构造函数一样),如下:

struct point { int x; int y; point(int z):x(z),y{z}{}//这里构造函数的参数列表里用{}就是赋值 }; point p6{4};//4赋给z,z赋给x和y.

一般没有变量名或对象名的操作使用在返回值return , 其它地方还是要有名字来操作。

一.返回值中的使用

直接在类型的后面接上一对大括号,大括号里面写每个构造函数参数的值,或者没有构造函数的情况下写每个成员变量的值,然后这一个整体就构成一个表达式,返回一个这个类型的实例.

Vector operator+(Vector a,Vector b) { return Vector{a.x+b.x,a.y+b.y};//没有对象名,但是已经生成了一个对象 }

如果上述不用{}通用初始化语法,则需要在函数中实例化一个对象,最后return这个对象。如下: 显然这种方法较为麻烦。

Vector operator+(Vector a,Vector b) { Vector c; c.x=a.x+b.x; c.y=a.y+b.y; return c; }

这里边有个小bug,返回类的对象时应该会调用复制构造函数,但是这里没有 引申一下: 一般有三种情况会调用复制构造函数: 1.当用类一个对象去初始化另一个对象时。point a = b;或point a(b);

2.如果函数形参是类对象。void test(point p){}

3.如果函数返回值是类对象,函数执行完成返回调用时。

point test() { point p; return p ; } point test() { return point{} ; }

前两种经过测试都会调用复制构造函数,维度第三个不行。后查找资料得到结果: 参考文章

2.类的实例化对象初始化

下图代码 Point a{1,2}; 就直接将类的成员变量进行了初始化;

如果不用{}通用初始化语法,用如下语法: Point a(1,2);也可以初始化,这个时候调用的是类的构造函数对它初始化,在类中要写好构造函数才行。

#include <iostream> #include <string> using namespace std; /* 请在这里定义struct */ struct Point { int x; int y; }; struct Vector { int x; int y; }; Vector operator+(Vector a,Vector b) { return Vector{a.x+b.x,a.y+b.y}; } Point operator+(Point a,Vector b) { return Point{a.x+b.x,a.y+b.y}; } Point operator+(Vector a,Point b) { return Point{a.x+b.x,a.y+b.y}; } int main() { Point a{1,2}; // Vector b{3,4}; auto x = b+b; cout<< "b + b = {"<<x.x<<", "<<x.y<<"}"<<endl; auto y = a+b; cout<< "a + b = {"<<y.x<<", "<<y.y<<"}"<<endl; auto z = b+a; cout<< "b + a = {"<<z.x<<", "<<z.y<<"}"<<endl; return 0; }

3.模本类Vector(动态数组) vector的常见使用方法

vector<类型>对象名(数组长度,元素初值);

vector<int> a(101;//定义了一个大小为10的整型动态数组,初始化全部为1

这种模板类也是用构造函数进行初始化的;

用new申请动态数组:

int *a=new int[n];//动态分配n个整型长度的内存给a,这个数组名就为a int *a=new int; //动态分配了一个整型内存,把地址给a,没有初始化 int *a=new int(1);//动态分配了一个整型内存,把地址给a,将这个内存初始化为1 int *a=new int{1};//与上述同样的效果 Line *line; line = new Line();//动态分配了一个类Line内存,把地址给line,调用这个类的构造函数将这个内存初始化 line = new Line{}//这个与上面是同样的效果,也会调用构造函数初始化

4.用new动态分配

#include <iostream> #include <string> using namespace std; struct point { int x; int y; //point(int z) : x{z}, y(z){}; }; int main() { auto p = new point[3]{{1,2},{3},{5,6}}; auto p1 = new point{1,2}; cout << p[1].y << endl; return 0; }
最新回复(0)