一.统一的列表初始化
在C++98中,标准允许使用花括号{}对数组或者结构体元素进行统一的列表初始值设定。比如:
struct Point
{
int _x;
int _y;
};
int main()
{
int array1[] = { 1, 2, 3, 4, 5 };
int array2[5] = { 0 };
Point p = { 1, 2 };
return 0;
}
C++11扩大了用大括号括起的列表(初始化列表)的使用范围,使其可用于所有的内置类型和用户自定义的类型,使用初始化列表时,可添加等号(=),也可不添加。
struct Point
{
int _x;
int _y;
};
int main()
{
int x1 = 1;
int x2{ 2 };
int x3 = { 3 };
int array1[]{ 1, 2, 3, 4, 5 };
int array2[5]{ 0 };
Point p{ 1, 2 };
// C++11中列表初始化也可以适用于new表达式中
int* pa = new int[4]{ 0 };
}
创建对象时也可以使用列表初始化方式调用构造函数初始化,因此C++11支持多参数的隐式类型转换
class Date
{
public:
Date(int year, int month, int day)
:_year(year)
,_month(month)
,_day(day)
{
cout << "Date(int year, int month, int day)" << endl;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1(2022, 1, 1); // C++98
// C++11支持的列表初始化,这里会调用构造函数初始化
Date d3{ 2022, 1, 2 };
Date d4 = { 2022, 1, 3 };
return 0;
}
二.声明
2.1 auto
在C++98中auto是一个存储类型的说明符,表明变量是局部自动存储类型,但是局部域中定义局部的变量默认就是自动存储类型,所以auto就没什么价值了。C++11中废弃auto原来的用法
将其用于实现自动类型判断。这样要求必须进行显示初始化,让编译器将定义对象的类型设置为初始化值的类型。
int main()
{
int i = 10;
auto p = &i;
auto pf = strcpy;
cout << typeid(p).name() << endl;
cout << typeid(pf).name() << endl;
map<string, string> dict = { {"sort", "排序"}, {"insert", "插入"} };
//map<string, string>::iterator it = dict.begin();
auto it = dict.begin();
}
2.2 decltype
关键字decltype将变量的类型声明为表达式指定的类型。
// decltype的一些使用使用场景
template<class T1, class T2>
void F(T1 t1, T2 t2)
{
decltype(t1 * t2) ret;
cout << typeid(ret).name() << endl;
}
int main()
{
const int x = 1;
double y = 2.2;
decltype(x * y) ret; // ret的类型是double
decltype(&x) p; // p的类型是int*
cout << typeid(ret).name() << endl;
cout << typeid(p).name() << endl;
F(1, 'a');
}
2.3 nullptr
由于C++中NULL被定义成字面量0,这样就可能回带来一些问题,因为0既能指针常量,又能表示整形常量。所以出于清晰和安全的角度考虑,C++11中新增了nullptr,用于表示空指针。
2.4 delete
C++11扩展delete的用法,delete除了释放new申请的源外,如果在默认成员函数后跟上=delete,表示让编译器除掉该默认成员函数。\
2.5 final和override
final:修饰虚函数,表示该虚函数不能再被重写,也同可以修饰类让类不能被继承
override: 检查派生类虚函数是否重写了基类某个虚函数,如果没有重写编译报
2.6 default
假设你要使用某个默认函数,但是因为一些原因这个函数没有默认生成。比如:我们提供了拷贝构造,就不会生成默认移动构造了,那么我们可以使用default关键字显示指定默认移动构造生成。 这个移动构造后面会说这里先了解
2.7 范围for循环
之前讲过这里就不进行讲解!
2.8 智能指针
后面详细讲解!
2.9 STL的变化
关于C++11新容器的变化只需要记得引进了哈希(unordered_map和unordered_set)即可
三.左值引用(&)和右值引用(&&)
3.1 认识左值引用和右值引用
传统的C++语法中就有引用的语法,而C++11中新增了的右值引用语法特性,所以从现在开始我们之前学习的引用就叫做左值引用。无论左值引用还是右值引用,都是给对象取别名。
什么是左值?(可以取地址的值)什么是左值引用?(左值的别名)
左值是一个表示数据的表达式(如变量名或解引用的指针),我们可以获取它的地址+可以对它赋值,左值可以出现赋值符号的左边,右值不能出现在赋值符号左边。
定义时const修饰符后的左值,不能给他赋值,但是可以取它的地址。左值引用就是给左值的引用,给左值取别名
int main()
{
// 以下的p、b、c、*p都是左值
int* p = new int(0);
int b = 1;
const int c = 2;
// 以下几个是对上面左值的左值引用
int*& rp = p;
int& rb = b;
const int& rc = c;
int& pvalue = *p;
}
什么是右值?(不可以取地址的值)什么是右值引用?(右值的别名)
右值也是一个表示数据的表达式,如:字面常量、表达式返回值,函数返回值(这个不能是左值引用返回)……
右值可以出现在赋值符号的右边,但是不能出现出现在赋值符号的左边,右值不能取地址。右值引用就是对右值的引用,给右值取别名。
int main()
{
double x = 1.1, y = 2.2;
// 以下几个都是常见的右值
10;
x + y;
fmin(x, y);
// 以下几个都是对右值的右值引用
int&& rr1 = 10;
double&& rr2 = x + y;
double&& rr3 = fmin(x, y);
// 这里编译会报错:error C2106: “=”: 左操作数必须为左值
10 = 1;
x + y = 1;
fmin(x, y) = 1;
}
需要注意的是右值是不能取地址的,但是给右值取别名后,会导致右值被存储到特定位置,且可以取到该位置的地址。
此时你可能会有一个疑问:如果右值被取别名后,它是会被存在特定位置,该位置可以取地址,如果我指针指向这里,我对指针修改会影响到该右值吗?
是的,可以修改,并且确实会影响那个“右值”——但前提是:这个右值是一个可修改的临时对象
int getValue() { return 42; } // 返回一个临时 int 对象
int&& rr = getValue(); // ✅ 合法!rr 绑定到临时对象
int* p = &rr; // ✅ 可以取地址
*p = 100; // ✅ 修改成功!临时对象被改变
std::cout << rr; // 输出 100
但是如果右值是字面量,它只能被const 右值引用绑定,因此无法对此进行修改
const int&& rr = 10;
// int* p = &rr; // ❌
// *p = 100; // 不可以修改
这个了解一下实际中右值引用的使用场景并不在于此,这个特性也不重要。
3.2 认识左值引用和右值引用比较
左值引用总结:
-
左值引用只能引用左值,不能引用右值。
-
但是const左值引用既可引用左值,也可引用右值
int main()
{
// 左值引用只能引用左值,不能引用右值。
int a = 10;
int& ra1 = a; // ra为a的别名
//int& ra2 = 10; // 编译失败,因为10是右值
// const左值引用既可引用左值,也可引用右值。
const int& ra3 = 10;
const int& ra4 = a;
return 0;
}
右值引用总结:
-
右值引用只能右值,不能引用左值。
-
但是右值可以引用move以后的左值。
-
右值的分类:内置类型(纯右值)自定义类型(将亡值)
int main()
{
// 右值引用只能右值,不能引用左值。
int&& r1 = 10;
// error C2440: “初始化”: 无法从“int”转换为“int &&”
// message : 无法将左值绑定到右值引用
int a = 10;
int&& r2 = a;
// 右值引用可以引用move以后的左值
int&& r3 = std::move(a);
}
本节课的重点很多,不过最重点的还是左值引用和右值引用,本节课只是带来开胃小菜,下节课将给大家重点分析右值引用为什么出现,它是解决了左值引用的那种问题!
5363

被折叠的 条评论
为什么被折叠?



