原始字面意
使用原始字面意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,则为八进制,若前缀为0x或0X,则为十六进制,否则为十进制
// 定义于头文件 <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 intauto限制
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 |
– |
