# 原始字面意

使用原始字面意 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 传出参数,记录从那 个字符 开始无法继续进行解析,比如;123 a bc ,传出位置为 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_asser t : 静态断言是在 编译时 就能够进行 检查的断言

# 参数

  • 参数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 :该函数 不会抛出异常
  • fals e, 可能抛出异常

# 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布尔型11true,false
char字符型11-128~127
unsigned char无符号字符型110~255
short短整型22-32768~32767
unsigned short无符号短整型220~65535
int整型44-2147483648~2147483647
unsigned int无符号整型440~4294967295
long长整型48
unsigned long无符号长整型48
unsigned long long无符号超长整型至少 8至少 88 字节取值范围: 0 ~ 264
float单精度浮点数44范围 - 2128 ~ 2128 精度为 6~7 位有效数字
double双精度浮点数88范围 - 21024 ~ 21024 精度为 15~16 位
long double扩展精度浮点数88范围 - 21024 ~ 21024 精度为 15~16 位
*地址(指针)48