一. 引入
简单地说: enable_shared_from_this
是为了解决 在类的内部获取自己的 shared_ptr 这件事情而存在的。
众所周知, 每一个对象都能通过this 指针来访问自己的地址。this 指针也是所有成员函数的隐含参数。然而有些时候,我们需要的不仅是 this,而是一个 "this的智能指针"。
这里有一个常见的场景:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
class A { public: A() :did_it_(false) {} ~A() { std::cout << "destoried" << std::endl; } void OnDo(bool did) { did_it_ = did; std::cout << "somthing did" << std::endl; } void DoSth_Async() { std::thread t([this]() { std::this_thread::sleep_for(std::chrono::seconds(5)); //...do somthing OnDo(true); }); t.detach(); } private: bool did_it_; }; |
代码如上:在异步方法 DoSth_Async()
中调用了成员方法 OnDo(bool)
. 这里存在一个问题: 当 OnDo()
被调用的时候,该类的是否还在生存中:
|
int main(){ { std::shared_ptr<A> ptr(new A()); ptr->DoSth_Async(); } std::this_thread::sleep_for(std::chrono::seconds(5)); return 0; } |
智能指针 ptr
在出作用域后立即被释放。所以当 OnDo()
被调用的时候,其所在的对象实际已经被释放了。如果确保在 OnDo()
被调用的时候,该对象仍然在生命周期内呢?一个方便的方法便上在构建线程的时候,将该对象的 shared_ptr 传入到线程。在该线程的生命周期内,该对象就会一直存在。这是一种利用 shared_ptr 的 保活机制
。
继续阅读
数据类型
1.long long
long long 数据类型,提供至少 64 位的整型数据。
2.nullptr
C++11 推荐使用 nullptr 表示空指针,不再推荐使用 NULL 或 0 表示空指针。 NULL为从 C 语言中引进的,在 C 语言中一般被定义为宏:
|
#ifdef __cplusplus #define NULL 0 #else #define NULL ((void*)0) #endif |
在 C 语言中,可以将 void* 隐式转换为任意指针类型,而在 C++ 中,可以为任意类型的指针赋 0 值。所以 c++ 将 NULL 定义为 0. nullptr 是指针类型(nullptr_t),该类型的对象不允许转换到非指针类型。
3.contexpr
1).const expression 常量表达式
是指值不会改变且在编译过程中就能得到计算结果的表达式。字面量属于常量表达式,使用常量表达式初始化的 const 对象也是常量表达式。一个对象或表达式是不是常量表达式要由它的数据类型和初始值共同决定:
|
const int max = 1024; // max 是常量表达式 const int min = max - 1000; // min 是常量表达式 int nsize = 64; // nsize 不是常量表达式 const int sz = nsize + 1; // nsize 不是常量表达式 |
尽管 size 变量的初始化值是字面常量 ,但是它的定义数据类型是 int 而不是 const int 。 尽管 sz 定义为 const int ,但其值需要运行时才能得到,所以它也不是常量表达式。
2).constexpr 变量
C++11 中,允许将变量声明为 constexpr 类型,以便由编译器检查变量是否为一个常量表达式:声明为 constexpr 的变量一定是一个常量 ,且必须使用常量表达式初始化:
|
constexpr int max = 1024; //是常量表达式 constexpr int min = max - 1000; //是常量表达式 constexpr int sz = get_size(); //只有当 get_size() 是常量表达式时,定义才是常量表达式 |
3).constexpr 函数
constexpr 可用于指示函数是一个常量表达式。这需要满足:
- 返回值类型是字面值类型
- 形参类型是字面值类型
- 函数体中必须有且仅有一条 return 语句
4).constexpr 与 const
|
const int* p = nullptr; //p 是一个指向整型常量的指针 constexpr int* q = nullptr; //q 是一个指向整型的常量指针 |
这里的 p 和 q 本质是不一样的。指针 p 指向的整数是常量,而指针 q 本身是常量,其指向的整数则可以不是常量:
|
*p = 5; //错误 ,p 指向的整数是一个常量,即 *p 是不可修改的 p = new int(0); //正确 , p 是可以修改的 *q = 5; //正确 , q 指向的整数的值是可以修改的 q = new int(0); //错误 , q 是一个常量表达式,不可修改 |
其中的关键在于constexpr把它所定义的对象置为了顶层const.
4.noexcept
noexcept 指示一个函数不会抛出异常。如果一个使用 noexcept 修饰的函数内部抛出了异常,编译器并不会报错,但
继续阅读