原始字面意

使用原始字面意R可以直接表示字符串的实际含义,而不需要额外对字符串做转义或连接操作
原始字符串必须用括号()括起来,括号的前后可以加其它字符串,所加的字符串会被忽略,并且两边字符串必须相同

#include <iostream>
using namespace std;
int main(void)
{
	//括号两边的字符串相同,并且会被忽略
	string str = R"foryouos:(D:\foryouos\blog#"C++新特性")foryouos:";
	cout << str << endl;
	return 0;
}
//输出: D:\foryouos\blog#"C++新特性"

final

C++中final关键字来限制某个类不能被继承,或者某个虚函数不能被重写,

// 使用final关键字修饰过的类不允许被继承,此类不能有派生类
class final Base
{
public:
	virtual void test()
	{
		cout <<"base class";
	}
	void test2() final; //此函数不能被重写
}

override

多态性确保在派生类中声明重写函数与基类的虚函数相同的签名,同时也确保表明将会重写基类的虚函数,确保重写的虚函数的正确性

to_string()

各种数值类型转换为字符串类型,是一个重载函数 位于 <string>头文件

#include <iostream>
#include <string>
using namespace std;
int main(void)
{
	string str = "pie is" + to_string(3.1415926);
	cout << str << endl;
	return 0;
}
//输出: pie is3.141593

字符串转换为数值

  • str 要转换的字符串
  • pos传出参数,记录从那个字符开始无法继续进行解析,比如;123abc ,传出位置为3
  • base:若base为0,则自动检测数值进制,若前缀为0,则为八进制,若前缀为0x0X,则为十六进制,否则为十进制
// 定义于头文件 <string>
int       stoi( const std::string& str, std::size_t* pos = 0, int base = 10 );
long      stol( const std::string& str, std::size_t* pos = 0, int base = 10 );
long long stoll( const std::string& str, std::size_t* pos = 0, int base = 10 );

unsigned long      stoul( const std::string& str, std::size_t* pos = 0, int base = 10 );
unsigned long long stoull( const std::string& str, std::size_t* pos = 0, int base = 10 );

float       stof( const std::string& str, std::size_t* pos = 0 );
double      stod( const std::string& str, std::size_t* pos = 0 );
long double stold( const std::string& str, std::size_t* pos = 0 );
  • 如果字符串全部是数值类型,全部会被转为对应的数值
  • 若前半部分是数值,那么前半部分会被转为数值
  • 如果第一个字符不是数值转换失败

举例

#include <iostream>
#include <string>
using namespace std;
int main()
{
    string str1 = "45";
    string str2 = "3.14159";
    string str3 = "9527 with words";

    int myint1 = stoi(str1);
    float myint2 = stof(str2);
    int myint3 = stoi(str3);


    cout << R"("str1=")" << myint1 << endl;
    cout << R"("str2=")" << myint2 << endl;
    cout << R"("str3=")" << myint3 << endl;
    return 0;
}
/*
"str1="45
"str2="3.14159
"str3="9527
*/

断言

断言就是将一个返回值总是需要为真的判断表达式放到语句中,用于排除在设计的逻辑上不应该发生的情况

#include <iostream>
#include <cassert>
using namespace std;
char* createArray(int size)
{
	// 通过断言判断数组大小是否大于0,
	// 必须大于0,才可以继续执行,否则程序中断
	assert(size > 0); 
}

静态断言

static_assert : 静态断言是在编译时就能够进行检查的断言

参数

  • 参数1: 断言表达式,此表达式需要返回一个bool值
  • 参数2:警告信息,一段字符串,在违反断言(表达式为false)时提示该信息
#include <iostream>
using namespace std;

int main(void)
{
	static_assert(sizeof(long) == 4, "错误,不是32位平台");
	return 0;
}

noexcept

表示其修饰的函数不会抛出异常,如果noexcept抛出了异常,编译器可以直接选择直接调用std::terminate()函数来终止程序运行。

double divisionMethod(int a,int b) noexcept(常量表达式);
  • 常量表达式:值为true:该函数不会抛出异常
  • false,可能抛出异常

auto

auto 类型 占位符 auto并不是在任意场景下都能推导出变量的实际类型,使用auto声明的变量必须要进行初始化,以让编译器推导出它的实际类型,在编译时将auto占位符替换为真正的类型

auto 变量名 = 变量值;

auto推导规则

  • 当变量不是指针或者引用类型时,推导的结果中不会保留const volatile关键字
  • 当变量是指针或者引用类型时,推导的结果中会保留const volatile关键字
int temp = 110;
auto *a = &temp;  // a的类型为int * ,auto推导为int
auto b = &temp;   // b的类型为int * ,auto推导为int*
auto &c = temp;    // c的类型为int& ,auto推导为int
auto d =temp;      // d的类型为int ,auto推导为int

int tmp = 130;
const auto a1 = tmp; // a1类型为const int auto被推导为int类型
auto a2 = a1;       // a2类型为const int ,但是a2没有生命指针或引用,auto 被推导为int
const auto &a3 = tmp;  // a3类型为const int& ,声明了引用,auto关键字被推导为int类型
auto &a4 = a3;      // a4数据类型 const int& ,声明了引用,auto 推到位const int

auto限制

  • auto 不能作为函数参数使用
  • auto 不能用于类的非静态成员变量初始化,可用于类的``静态常量变量初始化static const`
  • 不能使用auto 定义数组
  • 无法使用auto推导模版参数
//1,
int func(auto a, auto b);	// error
//2,
class Test
{
    auto v1 = 0;                    // error
    static auto v2 = 0;             // error,类的静态非常量成员不允许在类内部直接初始化
    static const auto v3 = 10;      // ok
}
//3,
int func()
{
    int array[] = {1,2,3,4,5};  // 定义数组
    auto t1 = array;            // ok, t1被推导为 int* 类型
    auto t2[] = array;          // error, auto无法定义数组
    auto t3[] = {1,2,3,4,5};;   // error, auto无法定义数组
}
//4,
template <typename T>
struct Test{}

int func()
{
    Test<double> t;
    Test<auto> t1 = t;           // error, 无法推导出模板类型
    return 0;
}  

auto应用

  • 用于STL的容器遍历
  • 用于泛型程序设计
#include <iostream>
#include <string>
using namespace std;

class T1
{
public:
    static int get()
    {
        return 10;
    }
};

class T2
{
public:
    static string get()
    {
        return "hello, world";
    }
};

template <class A>
void func(void)
{
    auto val = A::get();
    cout << "val: " << val << endl;
}

int main()
{
    func<T1>();
    func<T2>();
    return 0;
}

decltype

decltype - declare type 声明类型,在编译器编译的时候推导出表达式的类型

decltype(表达式)
int a = 10;
decltype(a) b = 99;                 // b -> int
decltype(a+3.14) c = 52.13;         // c -> double
decltype(a+b*c) d = 520.1314;       // d -> double

推导规则

  • 表达式为普通变量或者普通边大师或者类表达式,--decltype推导出的类型和表达式一致
  • 表达式是函数调用,使用decltype推导出的类型和函数返回值一致
  • 表达式是一个左值,或者被括号()包围,使用decltype推导出的是表达式类型的引用(如果有const volatile限定符不能忽略)
#include <iostream>
#include <vector>
using namespace std;

class Test
{
public:
    int num;
};

int main() {
    const Test obj;
    //带有括号的表达式
    decltype(obj.num) a = 0;  //a的类型为int
    decltype((obj.num)) b = a; //带括号,const int&   //obj有const限定符
    //加法表达式
    int n = 0, m = 0;
    decltype(n + m) c = 0;   // c类型为int
    decltype(n = n + m) d = n;  // 得到一个左值,d类型为int &
    return 0;
}

枚举

C枚举的使用

在枚举类型中枚举值编译器会自动从0开始赋值,然后依次向下递增。Red=0,Green=1,Blue=2

// 匿名枚举
enum {Red,Green,Blue};
// 有名枚举
enum Colors{Red,Green,Blue};

缺点

具有名字的enum类型的名字,以及enum成员的名字都是全局可见,若两个枚举内部成员出现相同就会报错重定义

强类型枚举

C++11枚举类型即枚举类,又称强类型枚举(strong-typed enum) ,只需在enum后加上关键字class

// 定义强类型枚举
enum class Colors{Red,Green,Blue};

优势

  • 强作用域: 不能输出到其父作用域空间
  • 只能是有名枚举
  • 转换限制,强类型枚举成员不可以整形隐私相互转换,可以强制类型转换
  • 可以指定底层类型。强类型默认底层类型int ,可以在名称后加 :type ,其中type可以是wchar_t以外的任何整形
enum class Colors{Red,Green,Blue};
(int)Colors::Red  //此转换合法

32位和64位系统个数据类型对比

数据类型 说明 32位字节数 64位字节数 取值范围
bool 布尔型 1 1 true,false
char 字符型 1 1 -128~127
unsigned char 无符号字符型 1 1 0~255
short 短整型 2 2 -32768~32767
unsigned short 无符号短整型 2 2 0~65535
int 整型 4 4 -2147483648~2147483647
unsigned int 无符号整型 4 4 0~4294967295
long 长整型 4 8
unsigned long 无符号长整型 4 8
unsigned long long 无符号超长整型 至少8 至少8 8字节取值范围: 0 ~ 264
float 单精度浮点数 4 4 范围-2128 ~ 2128 精度为6~7位有效数字
double 双精度浮点数 8 8 范围-21024 ~ 21024 精度为15~16位
long double 扩展精度浮点数 8 8 范围-21024 ~ 21024 精度为15~16位
* 地址(指针) 4 8