Virutal 析构函数 99%的类的析构函数都要声明成virtual,因为要继承给子类,然后子类能正确释放自己的资源
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 class Base { public : Base() { std ::cout << "Base ConStructor\n" ; } ~Base() { std ::cout << "Base Destructor\n" ; } };class Derived :public Base {public : Derived() :m_Array(new int [5 ]{1 ,2 ,3 ,4 ,5 }) { std ::cout << "Derived Constructor\n" ; } ~Derived() { delete [] m_Array; std ::cout << "Derived Destructor\n" ; } int * GetPtr () { return m_Array; }private : int *m_Array; };int main () { Base* base = new Base(); delete base; std ::cout << "---------------" << std ::endl ; Derived* derived = new Derived(); delete derived; std ::cout << "---------------" << std ::endl ; Base* ploy = new Derived(); int * ptr =((Derived*)ploy)->GetPtr(); delete ploy; std ::cin .get(); }
结构化绑定,接收std::tuple<>的语法糖
c++17
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 std::tuple<std::string,int> CreatePerson() { return {"abc" ,10 }; }struct res { std ::string name; int age; };int main () { auto person = CreatePerson(); const std ::string & name = std ::get<0 >(person); int age = std ::get < 1 >(person); auto [name,age] = CreatePerson(); std ::cout << name << " " << age << std ::endl ; std ::cin .get(); }
std::optional<>,对返回空值进行包装 根据函数返回值进行判断是否执行成功,使用std::optional<>
来包装
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 #include "../src/include/local.h" std ::optional<std ::string > ReadFileAsString (const std ::string & filepath) { std ::ifstream stream (filepath) ; if (stream) { std ::string result; stream.close(); return result; } return {}; }int main () { std ::optional<std ::string > data = ReadFileAsString("data.txt" ); if (data.has_value()) { std ::cout << "File read successfully!\n" ; } else { std ::string & string = *data; std ::cout << "File couldn't open" ; } std ::optional<int > count; int c = count.value_or(100 ); int c1 = *count; std ::cout << c << "\n" << c1; std ::cin .get(); }
std::variant<>多类型的数据存放在单一变量 但是同时只能存储一个类型的变量,注意和std::tuple<>
的区别,
大小等于所有类型之和,可使用在函数返回
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 enum class ErrorCode { None = 0 , NotFound = 1 , NotAccess = 2 }; std::variant<std::string, ErrorCode> ReadFileAsString(std::string pathfile) { return ErrorCode::NotAccess; }int main () { std ::variant<std ::string , ErrorCode> res = ReadFileAsString("data.txt" ); int index = res.index(); if (index == 0 ) std ::cout << std ::get<0 >(res); else std ::cout << (int )std ::get<1 >(res); std ::cout << (int )std ::get<ErrorCode>(res); std ::cin .get(); }
std::any 单个变量存储任意类型数据 注意是非模板类 ,可以存储任意类型的变量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 #include "../src/include/local.h" #define ps(str) std::cout << str << std::endl std ::any Func () { return 1 ; }enum class ErrorCode { None = 1 , Access = 2 , NotFound = 3 };int main () { std ::any data; data = 2 ; data = std ::string ("Abc" ); data = "das" ; data = ErrorCode::Access; data = 1.0f ; std ::string & string = std ::any_cast<std ::string &>(data); auto res = Func(); if (res.type() == typeid (std ::string )) { std ::cout << "std::string" ; } else { std ::cout << "no" ; } std ::cout << std ::any_cast<int >(res); std ::cin .get(); }
std::string_view fast 因为std::string构造和类的函数操作都会在堆上分配内存,而减少在堆上分配内存的次数能够run fast.
std::string_view构造函数接收const char *
和长度,通过指针来操作原std::string
而不是在堆上分配内存
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 #include "../src/include/local.h" #define ps(str) std::cout << str << std::endl uint32_t s_AllocCount = 0 ;void * operator new (size_t size) { s_AllocCount++; std ::cout << "Allocating " << size << " bytes\n" ; return malloc (size); }#define STRING_VIEW 1 #if STRING_VIEW void PrintName ( std ::string_view name) { std ::cout << name << std ::endl ; }#else void PrintName (const std ::string & name) { std ::cout << name << std ::endl ; }#endif int main () { std ::string name = "Yan Chernikov" ;#if STRING_VIEW std ::string_view firstName (name.c_str(), 3 ) ; std ::string_view lastName (name.c_str() + 4 , 9 ) ;#else std ::string firstName = name.substr(0 ,3 ); std ::string lastName = name.substr(4 , 9 );#endif PrintName("Cherno" ); PrintName(firstName); PrintName(lastName); std ::cout << s_AllocCount << " allocations" << std ::endl ; std ::cin .get(); }
使用chrome::tracing查看json格式的benchmark数据 生成json格式的benchmark数据,
用chrome::tracing打开
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 #include "../src/include/local.h" #define _CRT_SECURE_NO_WARNINGS #define ps(str) std::cout << str << std::endl struct ProfileResult { std ::string Name; long long Start, End; };struct InstrumentationSession { std ::string Name; };class Instrumentor { private : InstrumentationSession* m_CurrentSession; int m_ProfileCount; std ::ofstream m_OutputStream;public : Instrumentor() :m_CurrentSession(nullptr ),m_ProfileCount(0 ) { } void BeginSession (const std ::string &name,const std ::string &filepath = "results.json" ) { m_OutputStream.open(filepath); WriteHeader(); m_CurrentSession = new InstrumentationSession{name}; } void EndSession () { WriteFooter(); m_OutputStream.close(); delete m_CurrentSession; m_CurrentSession = nullptr ; m_ProfileCount = 0 ; } void WriteProfile (const ProfileResult& result) { if (m_ProfileCount++ > 0 ) m_OutputStream << "," ; std ::string name = result.Name; std ::replace(name.begin(),name.end(),'"' ,'\'' ); m_OutputStream << "{" ; m_OutputStream << "\"cat\":\"function\"," ; m_OutputStream << "\"dur\":" << (result.End - result.Start) << "," ; m_OutputStream << "\"name\":\"" << name << "\"," ; m_OutputStream << "\"ph\":\"X\"," ; m_OutputStream << "\"pid\":0," ; m_OutputStream << "\"tid\":0," ; m_OutputStream << "\"ts\":" << result.Start; m_OutputStream << "}" ; m_OutputStream.flush(); } void WriteHeader () { m_OutputStream << "{\"otherData\": {},\"traceEvents\":[" ; m_OutputStream.flush(); } void WriteFooter () { m_OutputStream << "]}" ; m_OutputStream.flush(); } static Instrumentor& Get () { static Instrumentor* instance = new Instrumentor(); return *instance; } };class InstrumentationTimer { public : InstrumentationTimer(const char * name) :m_Name(name),m_Stopped(false ) { m_StartTimepoint = std ::chrono::high_resolution_clock::now(); } ~InstrumentationTimer() { if (!m_Stopped) { Stop(); } } void Stop () { auto endTimePoint = std ::chrono::high_resolution_clock::now(); long long start = std ::chrono::time_point_cast<std ::chrono::microseconds>(m_StartTimepoint).time_since_epoch().count(); long long end = std ::chrono::time_point_cast<std ::chrono::microseconds>(endTimePoint).time_since_epoch().count(); Instrumentor::Get().WriteProfile({ m_Name,start,end }); m_Stopped = true ; }private : const char * m_Name; std ::chrono::time_point<std ::chrono::steady_clock> m_StartTimepoint; bool m_Stopped; };void Function1 () { InstrumentationTimer timer ("Function1" ) ; for (int i = 0 ; i < 1000 ; i++) { std ::cout << "Hello World #" << i << std ::endl ; } }void Function2 () { InstrumentationTimer timer ("Function2" ) ; for (int i=0 ; i<1000 ; i++) { std ::cout << "Hello World #" << sqrt (i) << std ::endl ; } }void RunBenchmarks () { InstrumentationTimer timer ("RunBenchmarks" ) ; Function1(); Function2(); }int main () { Instrumentor::Get().BeginSession("Profile" ); RunBenchmarks(); Instrumentor::Get().EndSession(); std ::cin .get(); }
Singleton(单例模式)或使用namespace来代替
单例模式就不解释了,添加一个cpp file,和一个头文件,实现单例模式效果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 #include "../src/include/local.h" #define ps(str) std::cout << str << std::endl class Random { private : Random() {} float m_RandomGenerator = 0.5f ; float IFloat () { return m_RandomGenerator; }public : Random(const Random&) = delete ; static float Float () { return Random::Get().IFloat(); } static Random& Get () { static Random* s_Instance = new Random(); return *s_Instance; } };namespace RandomClass { static float IFloat () ; static float s_RandomGenerator = 0.5f ; float Float () { return IFloat(); } }int main () { float ans = Random::Float(); std ::cout << ans << std ::endl ; float ans1 = RandomClass::Float(); std ::cout << ans1 << std ::endl ; std ::cin .get(); }namespace RandomClass { static float IFloat () { return s_RandomGenerator; } }