optional< T>
c++14中将包含一个std::optional类,optional< T>内部存储空间可能存储了T类型的值也可能没有存储T类型的值。当optional< T>被初始化之后,可以通过operator bool() 获得true的返回值,否则返回值为false,这样可以知道该optional内部是否有合法的一个T对象,进而继续访问。
optional<int> op; //未初始化,operator bool()为false if (op) cout << *op << endl; optional<int> op1 = 1; if (op) //经过初始化,返回true cout << *op1 << endl;
c++11实现optional
optional< T>要容纳T类型的对象,因此需要一个缓冲区来保存,该缓冲区可以使用普通的char数组,但是char xx[]是一字节对齐,xx很有可能不在MyClass对齐的位置上。这样调用placement new构造内存块,可能会引起效率问题或出错,因此需要用内存对齐的缓冲区 std::aligned_storage.
template<std::size_t Len, std::size_t Align> struct aligned_storage; Len表示所存储类型的size,通过sizeof(T)获得;Align表示该类型内存对齐的大小,通过std::alignment_of<T>::value获得。
std::aligned_storage一般和placement new结合起来使用:
struct A{ int avg; A(int a, int b):avg((a+b)/2){}; }; typedef std::aligned_storage<sizeof(A), std::aligenment_of<A>::value>::type Aligned_A; int main(){ Aligned_A a, b; //获得了两块内存区,大小和对齐方式指定 new (&a)A(10,20); //placement new,在内存块a处 构造了一个A对象 b = a; return 0; }
Optional的实现【代码均参考网上】
#include<type_traits> #include<iostream> #include<string> #include<map> using namespace std; template<typename T> class Optional { using data_t = typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type; public: Optional() : m_hasInit(false) {} Optional(const T& v) { Create(v); } Optional(T&& v) : m_hasInit(false) { Create(std::move(v)); } ~Optional() { Destroy(); } Optional(const Optional& other) : m_hasInit(false) { if (other.IsInit()) Assign(other); } Optional(Optional&& other) : m_hasInit(false) { if (other.IsInit()) { Assign(std::move(other)); other.Destroy(); } } Optional& operator=(Optional &&other) { Assign(std::move(other)); return *this; } Optional& operator=(const Optional &other) { Assign(other); return *this; } template<class... Args> void emplace(Args&&... args) { Destroy(); Create(std::forward<Args>(args)...); } bool IsInit() const { return m_hasInit; } explicit operator bool() const { return IsInit(); } T& operator*() { if (IsInit()) { return *((T*)(&m_data)); } throw std::logic_error("is not init"); } T const& operator*() const { if (IsInit()) { return *((T*)(&m_data)); } throw std::logic_error("is not init"); } bool operator == (const Optional<T>& rhs) const { return (!bool(*this)) != (!rhs) ? false : (!bool(*this) ? true : (*(*this)) == (*rhs)); } bool operator < (const Optional<T>& rhs) const { return !rhs ? false : (!bool(*this) ? true : (*(*this) < (*rhs))); } bool operator != (const Optional<T>& rhs) { return !(*this == (rhs)); } private: template<class... Args> void Create(Args&&... args) { new (&m_data) T(std::forward<Args> (args)...); m_hasInit = true; } void Destroy() { if (m_hasInit) { m_hasInit = false; ((T*)(&m_data))->~T(); } } void Assign(const Optional& other) { if (other.IsInit()) { Copy(other.m_data); m_hasInit = true; } else { Destroy(); } } void Assign(Optional&& other) { if (other.IsInit()) { Move(std::move(other.m_data)); m_hasInit = true; other.Destroy(); } else { Destroy(); } } void Move(data_t&& val) { Destroy(); new (&m_data) T(std::move(*((T*) (&val)))); } void Copy(const data_t& val) { Destroy(); new (&m_data) T(*((T*)(&val))); } private: bool m_hasInit; data_t m_data; }; class MyClass{ public: MyClass(int a, int b) : x_(a), y_(b){}; void print(){ cout << "x_ = " << x_ << endl; cout << "y_ = " << y_ << endl; } private: int x_; int y_; }; void TestOptional() { Optional<string> a("ok"); Optional<string> b("ok"); Optional<string> c("aa"); c = a; if (c<a) cout << '<' << endl; if (a == b) cout << '=' << endl; map<Optional<string>, int> mymap; mymap.insert(std::make_pair(a, 1)); mymap.insert(std::make_pair(c, 2)); auto it = mymap.find(a); cout << it->second << endl; Optional<MyClass> d; d.emplace(10, 20); (*d).print(); } int main(){ TestOptional(); return 0; }
原文链接: https://www.cnblogs.com/gtarcoder/p/4811429.html
欢迎关注
微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/221911
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!