C++ / Syntax
现代 C++ 语法笔记(五)
整理原始字面量、long long、成员初始化、模板、异常等现代 C++ 语法点。
using的使用
typedef
在C++中可通过typedef来给类型起别名,别名和原名完全等效
语法
//在变量声明前加上typedef,然后将变量名改成新类型名
//例
unsigned int a;
typedef unsigned int uint_t; //变量名a换成新类型名uint_t
int (*p)(int, double);
typedef (*funcPtr)(int, double) //变量名p换成新类型名funcPtr
using
用法和typedef没有太大区别,但在复杂场景更清晰
语法
using 旧类型名 = 新类型名;
例
using uint_t = unsigned int;
using funcPtr = int (*)(int, double);
可读性更好
此外,如果想固定一个key为int的map,即map<int, T>
typedef不支持给模板定义别名,会很麻烦,需要用到包装类(wrapper class)
如果使用using就很方便
template <typename T>
using intMap = map<int, T>;
左值右值,移动语义
左值:有名字,可以取地址
右值:临时对象
可以放在等号左边的就是左值,右值不行
右值可以被偷走资源,即移动
string s = string("hello");
此时可以直接移动到s,没必要拷贝给s之后再销毁
右值引用,&&
string&& r = string("hello");
此时r可以被修改,等于允许我们修改临时对象
std::move():将左值转换为可以移动的右值,但没有发生移动,只是返回了一个可以被移动的对象
string b = move(r); //此时才发生移动
被移动之后内存由新对象接管,原对象变为未定义,但仍可以使用
触发移动的时机:
- 返回值优化
srting f(){
return string("hello");
}
- push_back
vector<string> v;
v.push_back(string("hello"));
智能指针
用对象管理内存,对象销毁时自动释放内存,防止泄漏
unique_ptr 独占
shared_ptr 共享
weak_ptr 观察
unique_ptr
独占所有权,不能拷贝,可以移动
初始化:
unique_ptr<int> p = new int(10);
//or
auto p = make_unique<int>(10); //更推荐
unique_ptr<int> p2 = p1; //XXX,一块内存只能有一个主人
unique_ptr<int> p2 = move(p1); //正确,此时p1变为nullptr,p2拥有资源
shared_ptr
多个指针共享一块内存,可以拷贝,引用计数
auto p = make_shared<int>(10);
auto p2 = p1;
此时引用计数为2,当p1和p2都销毁时,引用计数变为0,自动销毁这块内存
shared_ptr内部有指针,引用计数,控制块
不能指向数组,需要指向数组的话要指定删除器,默认不允许
shared_ptr<int> p(new int(10), deleter);
weak_ptr
防止shared_ptr会出现的循环引用问题
不增加引用计数,只观察
auto sp = make_shared<int>(10);
weak_ptr<int> p1 = sp;
想要访问的话,需要用lock()升级成shared_ptr
if(auto tmp = p1.lock()){ //若已被销毁则会返回空
//可以使用
}