1.字符串的原始字面量
表达式:R"xxx(原始字符串)xxx"或者R"(原始字符串)",xxx要写的话,必须一样
//两种申明形式
string a = "aaa";//没有转义的时候就是原始字面量
string b = R"aaa(bbb)aaa";//申明为R"xxx()xxx"
string c = R"(ccc)";//申明为R"()"
string d = R"aaaa(ddd)aaaa";//申明为R"xxx()xxx"
cout << a<<b<<c<<d << endl;
意义:避免字符串中有转义字符时出现转义的问题,解决字符串过长(字符串写在多行中)而不想使用连接字符(\)的问题
//避免转义
string str = "hello\word\ttt";
string strR = R"(hello\word\ttt)";
cout << str << endl<< strR << endl;
string str2 = "hello\\word\\ttt";
cout << str2 << endl;
//解决字符串过长(字符串写在多行中)而不想使用连接字符(\)的问题
string str = "dsfhk\
dsfklhj\
dsklfhjsd\
<sd>\
sdfkgjyhk\
dsfg\
dfsgf\
dsrfgdrf";
string strR = R"(dsfhk
dsfklhj
dsklfhjsd
<sd>
sdfkgjyhk
dsfg
dfsgf
dsrfgdrf)";
cout << str << endl << strR << endl;
2.指针空值类型-nullptr
在C程序中,NULL表示(void*)0;在C++程序中,NULL表示0
void func(int a) {
cout << "func(int a)" << endl;
}
void func(char* a) {
cout << "func(char* a)" << endl;
}
//调用
func(10);
func(NULL);
func(nullptr);
C++中void*不能隐式转换成其他类型的指针
void* a = NULL;//NULL为0或者void *
int* b = NULL;//NULL为0或者void *
double* c = NULL;//NULL为0或者void *
char* d = NULL;//NULL为0或者void *
nullptr不能匹配类型;可以隐式的匹配指针类型,不能匹配类型。
void* ptr = nullptr;//nullptr隐式转成void*
int* test2 = nullptr;//nullptr隐式转成int*
double* test3 = nullptr;//nullptr隐式转成double*
char* test4 = nullptr;//nullptr隐式转成char*
3.常量-constexpr
c11之前的const有两个意思,修饰常量与变量只读
constexpr修饰常量表达式
常量变达式:多个常量(值不变)组成,且在编译过程中得到计算结果的表达式,达到提高程序执行效率的结果
定义常量const与constexpr是等价的,们都在编译过程得到结果
//定义常量时,const与constexpr是等价的
const int c = 33;//常量达表式
const int d = c + 1;//常量达表式
constexpr int h = 45;//常量达表式
constexpr int k = h + 3453;//常量达表式
对于C++内置数据类型可以使用constexpr修饰,使用class与struct自定义的数据类型不能使用constexpr修饰
常量表达式函数:constexpr修饰函数返回值的函数(普通函数、类成员\构造函数、模板函数)
常量表达式函数要求:
1.函数必须有返回值且返回值必须是常量表达式
2.函数使用前必须有对应的定义语句
3.整个函数体,不能出现常量表达式之外的语句(return除外)不能出现如using、typedef、static_assert断言、循环等
//常量表达式函数
constexpr int funConstexpr3() {
constexpr int a = 9;//a为常量
return a;
}
//constexpr修饰模板函数,会根据传入参数类型确定是否为常量表达式函数
template <typename TT>
constexpr TT display(TT t) {
return t;
}
//constexpr修饰构造函数,函数体必须为空.初始化必须为成员初始化列表
class MyClass3
{
public:
constexpr MyClass3():h(67) {}
int h;
};
在C++中建议把const与constexpr区分(即表示“只读”使用const,"常量"使用constexpr)
4.final
final可以修饰函数与类,放在函数或者累后面。
final修饰函数时,只能修饰虚函数(阻止子类重写父类的这个函数)
final修饰类时,防止类被继承(派生子类)
virtual不能与final同时出现
5.override
保证派生类中申明的重写函数与基类中的虚函数有相同的函数名,同时明确会重写基类的虚函数,保证重写虚函数的正确性。
6.模板的优化
1.模板的右尖括号>>
C11模板的多个右尖括号需要一个空格符fun<A<> >,之前连在一起是右移操作符
C11特性优化了这个fun<A<>>
2.模板的默认参数
函数模板能添加模板参数 template <typename T = int>
模板参数的优先级(从高到低):
1.显示指定参数类型
2.使用推导的参数类型
3.默认的模板参数类型
4.没有默认也不能推导除参数类型,则会报错
7.using与typedef
using与typedef定义类型的别名,不会创建新的类型
定义基础类型一样
typedef int int111;//typedef 旧的类型名 新的类型名(别名)
using int222 = int;//using 新的类型名(别名)= 旧的类型名
定义函数指针时,using更直观
typedef int(*funcc)(int, string);
using funccc = int(*)(int, string);//可读性
定义模板时,using能直接使用,typedef需要在定义外套一个类或者结构体
template <typename T>
//typedef ds<int, T> Ds;
//使用typedef时,需要使用class或者struct外包一层
struct MyStruct1
{
typedef map<int,T> Ds;
};
template <typename T>
using Um = map<int, T>;
8.基于范围的for循环
基于范围的for循环只访问一次后面的对象,多次遍历
使用迭代器模式的for循环多次判断边界,可以动态操作便利的对象
//vt:表达式、数组、容器、初始化列表
//&可以提高效率,修改原容器的值
for (auto& it : vt) {
cout << it++ << " ";
}
//只读
for (const auto& it : vt) {
cout << it << " ";
}