宏
函数名
void hello() {
std::cout << __func__ << std::endl;
}
只包含一次头文件
#pragma once
变长参数
#define LOG(...) printf(__VA_ARGS__)
int main() {
int x = 2;
LOG("x = %d", x);
}
noexcept 异常
声明函数不会抛异常
void BlockThrow() noexcept {
throw 1;
}
int main() {
try {
BlockThrow(); //结束进程
} catch (...) {
std::cout << "此句不会被打印" << std::endl;
}
}
声明函数可以抛异常
例如析够函数
class B {
~B() noexcept(false) {
throw 1; //异常被上层捕获
}
}
class A {
~A() {
throw 1; //直接结束进程
}
}
int main() {
try {
B b;
} catch(...) {
std::cout << "异常被捕获" << std::endl;
}
try {
A a;
} catch (...) {
std::cout<< "此句不会被打印" << std::endl;
}
}
初始化成员变量
class Room {
private:
int count = 1;
std::string name("Angel");
std::string owner{"Marry"};
}
继承
声明某个函数不能被子类改写: final
class SuperObj {
public:
virtual void fun() = 0;
}
class Base: public SuperObj {
public:
void fun() final;
}
class Room: public Base {
public:
void fun(); //无法编译通过
}
声明函数为继承函数:override
class SuperObj {
public:
virtual void fun() {
}
}
class Base: public SuperObj {
public:
void wrongFuncName() override; //父类没有这个函数,编译失败
}
继承构造函数
class A {
public:
A(int i) {}
A(double d, int i) {}
}
class C {
public:
C(int i) {}
C(string d) {}
}
struct B: A {
using A::A; //继承构造函数
using C::C;
B(int i) {} //解决冲突
}
模版
默认参数
template <class T, class U = double>
void f(T t = 0, U u = 0);
void g() {
f(1, 'c'); //pass
f(1); //pass
f(); //error
}
外部模版
保证相同的模版函数,只被实例化一次,减轻编译器的负担
#include "test.h"
template void fun<int>(int); //显示实例化
void test1() { fun(3); }
#include "test.h"
extern template void fun<int>(int); //外部模版声明,不会实例化
void test2() { fun(3); }
move
std::move是把左值转变为右值
它结合移动构造函数,可以做到转移资源
move的定义如下
static_cast<T&&>(lvalue)
forward
完美转发
把参数(无论是右值还是左值),直接从父函数,传递到子函数
template <typename T>
void IamForwording(T && t) {
RunCode(forward<T>(t));
}
模版别名
typedef std::vector<std::string> strvec;
using stdvec = std::vector<std::string>;
auto
类型推导
auto name = "name";
for
for(int & e: arr) { //arr必须是能够知道大小的类
cout << e;
}
强类型枚举
智能指针
- unique_ptr
- shared_ptr
- weak_ptr
原子类型
多线程变量
atomic<long long> total {0};
void func(int) {
for(int i=0; i< 100000; ++i) {
total+=i;
}
}
int main() {
thread t1(func, 0);
thread t2(func, 0);
t1.join();
t2.join();
cout << total << endl;
return 0;
}
自旋锁
atomic_flag lock = ATOMIC_FLAG_INIT;
while(lock.test_and_set(std::memory_order_acquiire)) {
cout<< "waiting" << endl;
}
...
lock.clear();
顺序一致性
- memory_order_relaxed: 不对执行顺序做保证
- Memory_order_acquire:本线程中,后续的所有读操作,都必须在本原子操作后执行
- Memory_order_release:本线程中,所有前面的写操作,都必须完成,才执行本原子操作
- Memory_order_acq_rel
- Memory_order_consume:本线程中,后续所有的原子操作,都必须在本原子操作后才执行
- Memory_order_seq_cst:全部原子操作,按顺序执行
atomic<int> a;
atomic<int> b;
int thread1(int) {
int t=1;
a.store(t, memory_order_relaxed);
b.store(t, memory_order_release);
}
int thread2(int) {
while(b.load(memory_order_acquire) != 2);
cout<< a.load(memory_order_relaxed) << endl;
}
线程局部变量
int thread_local err_code;
空指针
int* p = nullptr;
lambda
int main() {
int boys = 4, girls = 3;
auto totalChild = [=]()->int { return boys + girls; }
cout << totalChild();
}
原生字符串
cout << R "\n"
word << endl;
网友评论