C++11基础

C++11介绍

C++11是指C++编程语言的第11个版本,它于2011年发布。

C++11则带来了数量可观的变化,其中包含了约140个新特性,以及对C++03标准中约600个缺陷的修正,这使得C++11更像是从C++98/03中孕育出的一种新语言。C++11能更好地用于系统开发和库开发、语法更加泛华和简单化、更加稳定和安全,不仅功能更强大,而且能提升程序员的开发效率,公司实际项目开发中也用得比较多。

更多详情,可以去官网了解:C++11 - cppreference.com

列表初始化

{}初始化

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 x = { 10 };	// -> int x = 10
    int x2{ 10 };	// 可省略等号

	// 用户自定义初始化
	Point p1{ 3,5 };// 可省略等号

	//使用大括号对数组元素进行初始化
	int array1[]{1, 2, 3, 4, 5}; //可不添加等号
	int array2[5]{0};            //可不添加等号
    
	// c++11中列表初始化也可以用于new表达式(c++98不可用)
	int* p1 = new int[5]{ 0 };
	int* p2 = new int[5]{ 1,2,3,4,5 };
    
    //初始化标准库
	vector<int> v = { 1,2,3,4,5,6,7 };
	list<int> l{ 1,2,3,4,5 };
	map<int, double> myMap = { {1,1.0},{2,2.0} };
	return 0;
}

创建对象是,使用列表初始化方式调用构造函数

class Date
{
public:
	Date(int year, int month, int day)
		:_year(year)
		, _month(month)
		, _day(day)
	{}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	//一般调用构造函数创建对象的方式
	Date d1(2022, 8, 29);

	//C++11支持的列表初始化,会调用构造函数初始化
	Date d2 = { 2022, 8, 30 }; //可添加等号
	Date d3{ 2022, 8, 31 };    //可不添加等号
    
	return 0;
}

std::initializer_list

initializer_list是C++11引入的一种特殊类型,用于在对象构造过程中提供初始化列表

在这里插入图片描述

详细介绍文档


{}大括号括起的列表(初始化列表),使用auto自动类型推导,与typeid(变量名).name()的方式可以查看器类型
在这里插入图片描述


initializer_list是让其他容器支持列表初始化的,没有增删查改的接口

在这里插入图片描述

C++11给标准库中的容器增加了新的构造函数,以initalizer_list为参数

如vector容器:
在这里插入图片描述

当使用{}列表对容器进行初始化时,会识别成initializer_list类型,然后调用对应的构造函数对容器进行初始化

使用示例,模拟实现vector(initializer_list il):

namespace myVector
{
	template<class T>
	class vector {
	public:
		typedef T* iterator;

		// 使用 initializer_list 进行初始化
		vector(initializer_list<T> l)
		{
			_start = new T[l.size()];
			_finish = _start + l.size();
			_endofstorage = _start + l.size();

			iterator vit = _start;
            //typename 指明iterator为类型而非静态成员之类的
			/*typename initializer_list<T>::iterator lit = l.begin();
			while (lit != l.end()
			{
				*vit++ = *lit++;
			}*/

			for (auto e : l)
				*vit++ = e;
		}
	private:
		iterator _start;
		iterator _finish;
		iterator _endofstorage;
	};
}

通过在容器的构造函数中遍历initializer_list元素,完成初始化工作。

此外,赋值运算符重载同理在这里插入图片描述

vector<int> v;
v = { 1,2,3,4,5 };

变量类型推导

auto

在 c++11 中,auto 被重新定义为一个用于类型推导的关键字。

auto 主要用于让编译器根据初始值来确定变量的类型,简化代码的书写,减少类型重复,提高代码的可读性

int main()
{
	int i = 10;
	auto p = &i;
	auto pf = string("123");

	for(auto e : string){}
	return 0;
}

auto不仅可以减少代码的冗余,还能够避免自主声明类型可能导致的错误。


decltype

C++11中引入的关键字,用于获取表达式的类型。decltype(expression)

int x = 5;
decltype(x) y;       		// 推断y的类型为int

double func(int a, double b);
decltype(func(1, 2.0)) z;   // 推断z的类型为double,

int array[] = {1, 2, 3};
decltype(array) arr;    // 推断arr的类型为int[3]

decltype并不会执行表达式,在编译时分析表达式类型。

decltype特别是在模板编程中很有用,可以使代码更加灵活,更准确处理各种类型推断。

template<class T1, class T2>
// 推导函数的返回值类型
auto fun(T1 x, T2 y)
{
	return x + y;
}

int main()
{
	decltype(fun(1, 2)) ret1;
	cout << typeid(ret1).name() << endl; // int

	decltype(fun(1.1, 2.2)) ret2;
	cout << typeid(ret2).name() << endl; // double

	return 0;
}

typeid(变量名).name()只是用于获取变量类型,并以string返回字符串,无法通过其来定义变量。


STL中的改变

array

本质是静态数组,即定长数组
在这里插入图片描述

详细文档

//定义一个可存储10个int类型元素的array容器
array<int, 10> a1;  
  • arrary和普通数组一样,可以使用[]访问下标元素,创建后数组大小不能改变
  • arrary容器用类对数组进行封装,访问元素时会进行越界检查,[]是断言检查,at()是抛异常检查。对于普通数组,只有在写操作时会报错。

forword_list

单链表

在这里插入图片描述

参考:文档

使用很少

unordered_map与unordered_set

底层都使用哈希表,使用上与map和set差别不大

在这里插入图片描述

在这里插入图片描述

参考:详细文档

内置类型转string

可调用同一的函数to_string
在这里插入图片描述

string转内置类型

通过调用string类中对应的成员方法
在这里插入图片描述


类的新功能

默认成员函数

    在C++11前,每个类有6个默认成员函数:构造函数、析构函数、拷贝构造函数、拷贝赋值函数、取地址重载函数和const取地址重载函数。这六个函数中,前4个比较重要,后2个一般不会显示声明。默认,即如果没有声明定义,编译器会自动生成。

C++11标准新增两个默认成员函数:移动构造函数移动赋值运算符重载

对于这两个函数需要注意:

  • 移动构造函数的默认生成条件:自己没有实现移动构造函数,且没有实现析构函数、拷贝构造和拷贝赋值重载。
  • 移动赋值重载函数的生成条件:自己没有实现移动赋值重载函数,且没有实现析构函数、拷贝构造函数和拷贝赋值函数。

对于默认生成的移动构造函数:内置类型会执行逐成员按字节拷贝;自定义类型成员如果实现了就调用移动构造,没有实现就调用拷贝构造

默认移动赋值和移动构造完全类似。

参考:右值引用与移动构造

成员变量缺省值初始化

        默认的构造函数,对于内置类型是不做初始化的。于是C++11支持非静态成员变量在声明时使用缺省值,默认生成的构造函数会使用这些缺省值对成员进行初始化。

class Point
{
private:
    //声明缺省值
    int _x = 0;
    int _y = 0;
}

此操作并不是定义成员变量,而只是进行声明,使用默认构造函数时才创建

default

default关键字用于指示编译器生成默认的成员函数

示例:

类中已经定义了其他构造函数,也可以使用 default 关键字显式声明并定义一个默认构造函数

class Point
{
private:
	Point(int x, int y)
		:_x(x), _y(y)
	{}
	
    Point() = default;//显式声明默认构造函数
    //Point() {};
private:
    //声明缺省值
    int _x = 0;
    int _y = 0;
}

需要传参的构造函数与不需要传参的构造函数构成重载。当然,某些情况下,手动编写成员函可能更合适。


显示声明默认移动构造函数和移动赋值运算符重载

class MyClass {
public:
	Point(Point&& obj) = default;
	Point& operator=(Point&& obj) = default;
};

注意:default只能用于8种默认成员函数。

delete

delete关键字,可以用于删除这8中默认函数。

C++98中,可以将该函数设置成私有,并且只用声明不用定义,这样当外部调用该函数时就会报错

C++11时,在函数声明后加上=delete,用于删除类的默认成员函数,使其不能被调用

class Point
{
public:
    Point& operator=(const Point& ) = delete;//禁止调用赋值运算符
	~Point() = delete;//禁止调用析构函数
};

如果调用这些函数,编译时会报错,如:尝试引用已删除的函数


此外,delete关键字也可以用于删除某个函数的重载版本

void foo(int) {
    // 这个重载版本是可用的
}

void foo(double) = delete;   // 删除double类型的重载版本

int main() {
    foo(10);     // 调用foo(int)
    foo(3.14);   // 编译错误,无法调用被删除的重载版本
    return 0;
}

final与override

final关键字用于声明类不可被继承

class Base final {
// ...
};

// 编译错误,无法从final类派生出新的子类
class Derived : public Base {  
// ...
};

final关键字用于声明虚函数不可被重写

class Base {
public:
    virtual void foo() final {
        // ...
    }
};

class Derived : public Base {
public:
    // 编译错误,无法重写被标记为final的成员函数
    void foo(){   
        // ...
    }
};

override关键字用于表示派生类的成员函数重写(覆盖)了基类的虚函数。

它是一种编译期的标记,可以提高代码的可读性和安全性。

class Base {
public:
    virtual void foo() {
        // ...
    }
};

class Derived : public Base {
public:
    void foo() override {   // 使用override关键字重写基类的虚函数
        // ...
    }
};

会检查子类是否,重写了父类的某个虚函数,如果没有重写则编译会报错


    🦀🦀观看~~

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值