- 原始字符串
auto str = R"(will print the \n)";
- decltype:在编译期 根据变量名(或表达式)推断类型
int a = 1; double b = 2;
decltype(a+b) c = a+b;
// 还有一种用法,叫后置返回值类型
// 如下例子,无法直接写出 myAdd 的返回值类型,可能是 T1 或 T2,甚至是其他类型
// 这里可以直接用 表达式 a+b 用 decltype 来确定出最终类型
template<typename T1, typename T2>
auto myAdd(const T1& a, const T2& b) -> decltype(a+b) {
return a+b;
}
-
noexcept: 用于修饰方法,表示该方法肯定不会抛出异常,但如果该方法真的抛出了异常,那么程序会直接 abort,是无法 try-catch 住的
-
mutable 修饰 lambda:可使lambda可以修改捕获的变量
- 这只是针对 值捕获方式,而不是引用捕获
- 默认情况下,值捕获的变量,再lambda中默认都是const的
- 如果标记了 mutable,那么就能修改这些变量
- 但注意,因为是值捕获,所以lambda对变量的修改 是不会影响到 父作用域中的原始变量的
-
左值,右值
- 左值,等号左边的值,能被赋值,能取地址
- 声明定义的普通变量都是左值
- 右值,等号右边的值,不能被赋值,不能取地址
- 各种类型的字面值
- 表达式, 如 a+b 的结果
- 将亡值,函数的返回值(不论是函数里,还是调用处)
- 左值引用,即给左值变量 取别名
- 右值引用,给右值变量 取别名
int && a = 10; int b=1,c=2; int && d = a+c;
- 左值,等号左边的值,能被赋值,能取地址
-
std::move 将命中 对象的 移动拷贝构造
class Obj {
public: Obj(Obj&& o){}
};
- 右值引用 的目的就是为里解决代码中不必要的拷贝
- 完美转发:当 函数参数都以右值引用方式声明时,为里保证 右值引用 参数在流转时 一直都是 右值引用,需要在 传惨转发时 使用 std::forward(myRightRefVar)
- 完美转发:当 函数参数都以右值引用方式声明时,为里保证 右值引用 参数在流转时 一直都是 右值引用,需要在 传惨转发时 使用 std::forward(myRightRefVar)
- typedef 与 using 在定义类型别名的差异
- 都能用于定义类型别名
typedef int MYINT; using MYINT = int;
- 但在有模板情况下,using 更好
template<typename T> typedef std::vector<T> TVector; // 不支持, 语法错误 // 只能使用变通方案 template<typename T> struct TVectorWrapper { typedef std::vector<T> TVector; }; // 而 using 能支持 template<typename T> using TVector = std::vector<T>;
- std::bind
- 目的是为里封装C++中所有的可调用对象
- 全局函数
- 类对象函数
- 类静态函数
- 仿函数,重载了 operator()
- 可转换函数对象,重载了 能返回函数对象的 operator
- lambda
- 它能封装所有(或者部分)可调用对象的参数(包括this)
- 它将返回一个新的 std::function 对象
- bind 的一个很重要的 特点就是 将 函数(可调用对象) 的参数也封装了,但有一个问题,就是 调用bind时,所有的参数都是 值传递,这时,如果原函数(被封装的函数) 有一个参数时 引用传参数,则会有问题,这时就需要使用 std::ref 了
// 原函数,参数 a 以引用方式传参 void inc(int & a){ ++a; std::cout<<a<<std::endl; } int main() { // 需要被 inc 修改的值 int aa = 0; // 使用 bind 封装到 std::function 中 auto f = std::bind(inc, std::ref(aa)); // 如果不使用 std::ref 将无法修改到这里的 aa 的值 // 调用 f(); std::cout<<aa<<std::endl; return 0; }
- 目的是为里封装C++中所有的可调用对象