第37章 特殊工具和技术 C++20新特性:位操作库 C++20引入了<bit>库,提供了一系列用于位操作的函数:
位操作库的基本功能 位计数 :计算置位的位数位查找 :查找第一个或最后一个置位的位置位操作 :设置、清除、翻转位位旋转 :循环移位操作位操作库的使用示例 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 #include <bit> #include <iostream> #include <cstdint> int main () { uint8_t value = 0b10101010 ; int count = std::popcount (value); std::cout << "Number of set bits: " << count << std::endl; int first_set = std::countr_zero (value); std::cout << "First set bit position: " << first_set << std::endl; int last_set = std::countl_zero (value); std::cout << "Leading zeros: " << last_set << std::endl; uint8_t set_bit = std::setbit (value, 2 ); std::cout << "After setting bit 2: " << static_cast <int >(set_bit) << std::endl; uint8_t clear_bit = std::clearbit (value, 1 ); std::cout << "After clearing bit 1: " << static_cast <int >(clear_bit) << std::endl; uint8_t flip_bit = std::flipbit (value, 0 ); std::cout << "After flipping bit 0: " << static_cast <int >(flip_bit) << std::endl; uint8_t rotate_left = std::rotl (value, 1 ); std::cout << "After left rotation: " << static_cast <int >(rotate_left) << std::endl; uint8_t rotate_right = std::rotr (value, 1 ); std::cout << "After right rotation: " << static_cast <int >(rotate_right) << std::endl; bool is_power_of_two = std::has_single_bit (8 ); std::cout << "8 is power of two: " << std::boolalpha << is_power_of_two << std::endl; uint8_t next_power_of_two = std::bit_ceil (10 ); std::cout << "Next power of two after 10: " << static_cast <int >(next_power_of_two) << std::endl; return 0 ; }
位操作库的优点 标准化 :提供了跨平台一致的位操作接口优化 :实现经过了编译器优化,性能优异可读性 :使用命名函数替代位掩码,提高代码可读性安全性 :避免了手动位操作的常见错误完整性 :提供了全面的位操作功能类型转换运算符 static_cast static_cast用于相关类型之间的转换,是最常用的类型转换运算符。
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 #include <iostream> int main () { double d = 3.14 ; int i = static_cast <int >(d); std::cout << "double to int: " << i << std::endl; class Base { public : virtual ~Base () {} }; class Derived : public Base { public : void foo () { std::cout << "Derived::foo()" << std::endl; } }; Base* basePtr = new Derived (); Derived* derivedPtr = static_cast <Derived*>(basePtr); derivedPtr->foo (); delete basePtr; Derived derived; Base& baseRef = derived; Derived& derivedRef = static_cast <Derived&>(baseRef); derivedRef.foo (); return 0 ; }
dynamic_cast dynamic_cast用于多态类型之间的转换,运行时检查类型安全性。
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 #include <iostream> int main () { class Base { public : virtual ~Base () {} }; class Derived : public Base { public : void foo () { std::cout << "Derived::foo()" << std::endl; } }; class AnotherDerived : public Base { public : void bar () { std::cout << "AnotherDerived::bar()" << std::endl; } }; Base* basePtr1 = new Derived (); Derived* derivedPtr = dynamic_cast <Derived*>(basePtr1); if (derivedPtr) { derivedPtr->foo (); } AnotherDerived* anotherDerivedPtr = dynamic_cast <AnotherDerived*>(basePtr1); if (anotherDerivedPtr) { anotherDerivedPtr->bar (); } else { std::cout << "dynamic_cast failed: not an AnotherDerived" << std::endl; } try { Base& baseRef = *basePtr1; AnotherDerived& anotherDerivedRef = dynamic_cast <AnotherDerived&>(baseRef); anotherDerivedRef.bar (); } catch (const std::bad_cast& e) { std::cout << "dynamic_cast failed: " << e.what () << std::endl; } delete basePtr1; return 0 ; }
const_cast const_cast用于添加或删除const限定符。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #include <iostream> void func (int * ptr) { *ptr = 100 ; } int main () { const int x = 42 ; int * nonConstPtr = const_cast <int *>(&x); *nonConstPtr = 100 ; std::cout << "x: " << x << std::endl; int y = 42 ; const int * constPtr = const_cast <const int *>(&y); const int z = 42 ; func (const_cast <int *>(&z)); return 0 ; }
reinterpret_cast reinterpret_cast用于不相关类型之间的转换,是最危险的类型转换运算符。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #include <iostream> int main () { int x = 100 ; int * intPtr = &x; void * voidPtr = reinterpret_cast <void *>(intPtr); int * convertedPtr = reinterpret_cast <int *>(voidPtr); std::cout << "*convertedPtr: " << *convertedPtr << std::endl; uintptr_t intValue = reinterpret_cast <uintptr_t >(intPtr); std::cout << "Pointer as integer: " << intValue << std::endl; int * ptrFromInt = reinterpret_cast <int *>(intValue); std::cout << "*ptrFromInt: " << *ptrFromInt << std::endl; double d = 3.14 ; double * doublePtr = &d; int * intPtr2 = reinterpret_cast <int *>(doublePtr); return 0 ; }
运行时类型识别(RTTI) RTTI允许在运行时确定对象的类型,主要通过typeid运算符和dynamic_cast实现。
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 #include <iostream> #include <typeinfo> int main () { int i = 42 ; double d = 3.14 ; std::string s = "hello" ; std::cout << "Type of i: " << typeid (i).name () << std::endl; std::cout << "Type of d: " << typeid (d).name () << std::endl; std::cout << "Type of s: " << typeid (s).name () << std::endl; if (typeid (i) == typeid (int )) { std::cout << "i is an int" << std::endl; } class Base { public : virtual ~Base () {} }; class Derived : public Base {}; Base* basePtr = new Derived (); std::cout << "Type of *basePtr: " << typeid (*basePtr).name () << std::endl; Base baseObj; std::cout << "Type of baseObj: " << typeid (baseObj).name () << std::endl; delete basePtr; return 0 ; }
异常处理 基本异常处理 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 #include <iostream> #include <stdexcept> void divide (int a, int b) { if (b == 0 ) { throw std::runtime_error ("Division by zero" ); } std::cout << "Result: " << static_cast <double >(a) / b << std::endl; } int main () { try { divide (10 , 2 ); divide (10 , 0 ); } catch (const std::exception& e) { std::cout << "Exception caught: " << e.what () << std::endl; } catch (...) { std::cout << "Unknown exception caught" << std::endl; } return 0 ; }
自定义异常 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 #include <iostream> #include <stdexcept> class MyException : public std::exception {private : std::string message; public : MyException (const std::string& msg) : message (msg) {} const char * what () const noexcept override { return message.c_str (); } }; void validateAge (int age) { if (age < 0 ) { throw MyException ("Age cannot be negative" ); } if (age > 120 ) { throw MyException ("Age is out of range" ); } std::cout << "Valid age: " << age << std::endl; } int main () { try { validateAge (25 ); validateAge (-5 ); } catch (const MyException& e) { std::cout << "MyException caught: " << e.what () << std::endl; } catch (const std::exception& e) { std::cout << "std::exception caught: " << e.what () << std::endl; } return 0 ; }
异常规格说明(C++11前) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #include <iostream> void func () throw (int , double ) { throw 42 ; } void noThrowFunc () throw () { } int main () { try { func (); } catch (int e) { std::cout << "Caught int: " << e << std::endl; } return 0 ; }
noexcept说明符(C++11+) 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 #include <iostream> void noThrowFunc () noexcept { std::cout << "noThrowFunc()" << std::endl; } void conditionalNoThrowFunc (bool throwException) noexcept (noexcept (throwException)) { if (throwException) { } std::cout << "conditionalNoThrowFunc()" << std::endl; } template <typename T>void checkNoexcept () { std::cout << "std::is_nothrow_invocable_v<T()>: " << std::is_nothrow_invocable_v <T ()>() << std::endl; } int main () { noThrowFunc (); conditionalNoThrowFunc (false ); return 0 ; }
内存管理 智能指针(C++11+) 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 #include <iostream> #include <memory> class MyClass {private : int value; public : MyClass (int v) : value (v) { std::cout << "MyClass constructed: " << value << std::endl; } ~MyClass () { std::cout << "MyClass destructed: " << value << std::endl; } void foo () { std::cout << "MyClass::foo(): " << value << std::endl; } }; int main () { std::cout << "=== unique_ptr ===" << std::endl; std::unique_ptr<MyClass> uptr1 (new MyClass(1 )) ; uptr1->foo (); std::unique_ptr<MyClass> uptr2 = std::move (uptr1); uptr2->foo (); std::cout << "\n=== shared_ptr ===" << std::endl; std::shared_ptr<MyClass> sptr1 (new MyClass(2 )) ; std::cout << "Reference count: " << sptr1. use_count () << std::endl; { std::shared_ptr<MyClass> sptr2 = sptr1; std::cout << "Reference count: " << sptr1. use_count () << std::endl; sptr2->foo (); } std::cout << "Reference count: " << sptr1. use_count () << std::endl; sptr1->foo (); std::cout << "\n=== weak_ptr ===" << std::endl; std::weak_ptr<MyClass> wptr = sptr1; std::cout << "Reference count: " << sptr1. use_count () << std::endl; if (auto locked = wptr.lock ()) { locked->foo (); } sptr1. reset (); std::cout << "Reference count after reset: " << (wptr.expired () ? "0 (expired)" : "non-zero" ) << std::endl; std::cout << "\n=== make_unique and make_shared ===" << std::endl; auto uptr3 = std::make_unique <MyClass>(3 ); auto sptr3 = std::make_shared <MyClass>(4 ); uptr3->foo (); sptr3->foo (); return 0 ; }
内存池 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 #include <iostream> #include <vector> class MemoryPool {private : std::vector<void *> blocks; size_t blockSize; size_t capacity; size_t used; public : MemoryPool (size_t blockSize, size_t capacity) : blockSize (blockSize), capacity (capacity), used (0 ) { blocks.reserve (capacity); for (size_t i = 0 ; i < capacity; ++i) { blocks.push_back (std::malloc (blockSize)); } } ~MemoryPool () { for (void * block : blocks) { std::free (block); } } void * allocate () { if (used < capacity) { return blocks[used++]; } return nullptr ; } void deallocate (void * ptr) { for (size_t i = 0 ; i < used; ++i) { if (blocks[i] == ptr) { std::swap (blocks[i], blocks[--used]); break ; } } } size_t getUsed () const { return used; } size_t getCapacity () const { return capacity; } }; int main () { MemoryPool pool (sizeof (int ), 10 ) ; int * ptrs[5 ]; for (int i = 0 ; i < 5 ; ++i) { ptrs[i] = static_cast <int *>(pool.allocate ()); *ptrs[i] = i * 10 ; std::cout << "Allocated: " << *ptrs[i] << std::endl; } std::cout << "Used: " << pool.getUsed () << "/" << pool.getCapacity () << std::endl; pool.deallocate (ptrs[2 ]); std::cout << "After deallocating ptrs[2]: " << pool.getUsed () << "/" << pool.getCapacity () << std::endl; int * newPtr = static_cast <int *>(pool.allocate ()); *newPtr = 99 ; std::cout << "Reallocated: " << *newPtr << std::endl; std::cout << "Used: " << pool.getUsed () << "/" << pool.getCapacity () << std::endl; return 0 ; }
元编程 模板特化 1 2 3 4 5 6 #include <iostream> template <typename T>class MyClass {publ
继续完成模板特化的示例:
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 #include <iostream> template <typename T>class MyClass {public : static void print () { std::cout << "General template" << std::endl; } }; template <>class MyClass <int > {public : static void print () { std::cout << "Specialized for int" << std::endl; } }; template <>class MyClass <double > {public : static void print () { std::cout << "Specialized for double" << std::endl; } }; template <>class MyClass <const char *> {public : static void print () { std::cout << "Specialized for const char*" << std::endl; } }; int main () { MyClass<float >::print (); MyClass<int >::print (); MyClass<double >::print (); MyClass<const char *>::print (); return 0 ; }
模板元编程 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 #include <iostream> template <int N>struct Factorial { static constexpr int value = N * Factorial<N - 1 >::value; }; template <>struct Factorial <0 > { static constexpr int value = 1 ; }; template <int N>struct Fibonacci { static constexpr int value = Fibonacci<N - 1 >::value + Fibonacci<N - 2 >::value; }; template <>struct Fibonacci <0 > { static constexpr int value = 0 ; }; template <>struct Fibonacci <1 > { static constexpr int value = 1 ; }; template <typename T>struct is_integral { static constexpr bool value = false ; }; template <>struct is_integral <int > { static constexpr bool value = true ; }; template <>struct is_integral <long > { static constexpr bool value = true ; }; template <>struct is_integral <short > { static constexpr bool value = true ; }; template <>struct is_integral <char > { static constexpr bool value = true ; }; template <bool B, typename T, typename U>struct conditional { using type = T; }; template <typename T, typename U>struct conditional <false , T, U> { using type = U; }; int main () { std::cout << "Factorial<5>::value: " << Factorial<5 >::value << std::endl; std::cout << "Fibonacci<10>::value: " << Fibonacci<10 >::value << std::endl; std::cout << "is_integral<int>::value: " << is_integral<int >::value << std::endl; std::cout << "is_integral<double>::value: " << is_integral<double >::value << std::endl; using Type1 = conditional<true , int , double >::type; using Type2 = conditional<false , int , double >::type; std::cout << "Type1 is int: " << std::is_same_v<Type1, int > << std::endl; std::cout << "Type2 is double: " << std::is_same_v<Type2, double > << std::endl; return 0 ; }
可变参数模板(C++11+) 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 #include <iostream> template <typename T>void print (T value) { std::cout << value << std::endl; } template <typename T, typename ... Args>void print (T first, Args... rest) { std::cout << first << " " ; print (rest...); } template <typename ... Args>size_t countArgs (Args... args) { return sizeof ...(args); } template <typename ... Args>auto sum (Args... args) { return (args + ...); } int main () { print (1 , 2.5 , "hello" , true ); std::cout << "countArgs(1, 2, 3): " << countArgs (1 , 2 , 3 ) << std::endl; std::cout << "countArgs('a', 'b'): " << countArgs ('a' , 'b' ) << std::endl; std::cout << "sum(1, 2, 3, 4, 5): " << sum (1 , 2 , 3 , 4 , 5 ) << std::endl; std::cout << "sum(1.5, 2.5, 3.5): " << sum (1.5 , 2.5 , 3.5 ) << std::endl; return 0 ; }
并发编程(C++11+) 线程 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 #include <iostream> #include <thread> #include <vector> void func (int id) { std::cout << "Thread " << id << " started" << std::endl; std::this_thread::sleep_for (std::chrono::milliseconds (100 )); std::cout << "Thread " << id << " finished" << std::endl; } int main () { std::cout << "Main thread started" << std::endl; std::thread t1 (func, 1 ) ; std::thread t2 (func, 2 ) ; t1. join (); t2. join (); std::vector<std::thread> threads; for (int i = 3 ; i < 6 ; ++i) { threads.emplace_back (func, i); } for (auto & t : threads) { t.join (); } std::cout << "Main thread finished" << std::endl; return 0 ; }
互斥量 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 <iostream> #include <thread> #include <vector> #include <mutex> std::mutex mtx; int sharedData = 0 ; void increment (int id) { for (int i = 0 ; i < 1000 ; ++i) { std::lock_guard<std::mutex> lock (mtx) ; sharedData++; } } int main () { std::vector<std::thread> threads; for (int i = 0 ; i < 10 ; ++i) { threads.emplace_back (increment, i); } for (auto & t : threads) { t.join (); } std::cout << "Final sharedData: " << sharedData << std::endl; return 0 ; }
条件变量 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 #include <iostream> #include <thread> #include <mutex> #include <condition_variable> std::mutex mtx; std::condition_variable cv; bool ready = false ;int data = 0 ;void producer () { std::this_thread::sleep_for (std::chrono::milliseconds (500 )); { std::lock_guard<std::mutex> lock (mtx) ; data = 42 ; ready = true ; std::cout << "Producer: Data produced: " << data << std::endl; } cv.notify_one (); } void consumer () { std::cout << "Consumer: Waiting for data..." << std::endl; { std::unique_lock<std::mutex> lock (mtx) ; cv.wait (lock, []{ return ready; }); std::cout << "Consumer: Data received: " << data << std::endl; ready = false ; } } int main () { std::thread t1 (producer) ; std::thread t2 (consumer) ; t1. join (); t2. join (); return 0 ; }
原子操作 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 #include <iostream> #include <thread> #include <vector> #include <atomic> std::atomic<int > sharedData (0 ) ; void increment (int id) { for (int i = 0 ; i < 1000 ; ++i) { sharedData++; } } int main () { std::vector<std::thread> threads; for (int i = 0 ; i < 10 ; ++i) { threads.emplace_back (increment, i); } for (auto & t : threads) { t.join (); } std::cout << "Final sharedData: " << sharedData << std::endl; return 0 ; }
其他特殊工具 类型别名(typedef和using) 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 #include <iostream> #include <vector> typedef int Integer;typedef std::vector<int > IntVector;using Float = float ;using FloatVector = std::vector<float >;template <typename T>using Vector = std::vector<T>;int main () { Integer i = 42 ; IntVector iv = {1 , 2 , 3 , 4 , 5 }; Float f = 3.14 ; FloatVector fv = {1.1 , 2.2 , 3.3 }; Vector<int > v1 = {1 , 2 , 3 }; Vector<double > v2 = {1.1 , 2.2 , 3.3 }; std::cout << "i: " << i << std::endl; std::cout << "f: " << f << std::endl; return 0 ; }
枚举类(C++11+) 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 #include <iostream> enum Color { RED, GREEN, BLUE }; enum class Direction { UP, DOWN, LEFT, RIGHT }; enum class Status : int { OK = 0 , ERROR = 1 , WARNING = 2 }; int main () { Color color = RED; std::cout << "Color::RED: " << color << std::endl; Direction dir = Direction::UP; std::cout << "static_cast<int>(Direction::UP): " << static_cast <int >(Direction::UP) << std::endl; std::cout << "static_cast<int>(Status::OK): " << static_cast <int >(Status::OK) << std::endl; return 0 ; }
内联命名空间(C++11+) 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 #include <iostream> inline namespace V1 { void foo () { std::cout << "V1::foo()" << std::endl; } } namespace V2 { void foo () { std::cout << "V2::foo()" << std::endl; } } int main () { foo (); V2::foo (); V1::foo (); return 0 ; }
结构化绑定(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 24 25 26 27 28 29 30 31 32 33 34 #include <iostream> #include <tuple> #include <vector> #include <map> int main () { std::tuple<int , double , std::string> t (1 , 2.5 , "hello" ) ; auto [a, b, c] = t; std::cout << "a: " << a << ", b: " << b << ", c: " << c << std::endl; int arr[] = {1 , 2 , 3 }; auto [x, y, z] = arr; std::cout << "x: " << x << ", y: " << y << ", z: " << z << std::endl; struct Point { int x; double y; }; Point p = {10 , 20.5 }; auto [px, py] = p; std::cout << "px: " << px << ", py: " << py << std::endl; std::map<std::string, int > m = {{"one" , 1 }, {"two" , 2 }}; for (const auto & [key, value] : m) { std::cout << key << ": " << value << std::endl; } return 0 ; }
最佳实践 1. 类型转换 优先使用static_cast :对于相关类型之间的转换使用dynamic_cast :对于多态类型之间的转换,需要运行时检查谨慎使用const_cast :只在必要时使用,避免修改const变量避免使用reinterpret_cast :这是最危险的转换,尽量避免使用2. 异常处理 合理使用异常 :只对真正的异常情况使用异常捕获适当的异常 :从具体到一般捕获异常使用noexcept :对于不会抛出异常的函数,使用noexcept说明异常安全 :确保代码在抛出异常时保持一致的状态资源管理 :使用RAII管理资源,避免资源泄漏3. 内存管理 使用智能指针 :优先使用std::unique_ptr和std::shared_ptr使用std::make_unique和std::make_shared :避免裸指针避免循环引用 :使用std::weak_ptr打破循环引用内存池 :对于频繁分配和释放的小对象,考虑使用内存池4. 元编程 模板特化 :用于为特定类型提供定制实现SFINAE :用于基于类型特性选择不同的重载折叠表达式 :C++17+中用于简化可变参数模板的实现类型 traits :用于在编译时获取类型信息5. 并发编程 使用标准库 :优先使用std::thread、std::mutex等标准库组件避免共享状态 :尽量减少线程间的共享状态使用原子操作 :对于简单的共享变量,使用std::atomicRAII风格的锁 :使用std::lock_guard和std::unique_lock避免死锁 :使用std::scoped_lock或std::lock避免死锁常见错误和陷阱 1. 类型转换错误 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 int x = 42 ;std::string* strPtr = reinterpret_cast <std::string*>(&x); Base* basePtr = new Base (); Derived* derivedPtr = static_cast <Derived*>(basePtr); derivedPtr->foo (); Derived* derivedPtr = dynamic_cast <Derived*>(basePtr); if (derivedPtr) { derivedPtr->foo (); }
2. 异常处理错误 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 try { } catch (...) { } class MyClass {public : ~MyClass () { throw std::runtime_error ("Error in destructor" ); } }; class MyClass {public : ~MyClass () noexcept { try { } catch (...) { } } };
3. 内存管理错误 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 MyClass* ptr = new MyClass (); std::unique_ptr<MyClass> ptr = std::make_unique <MyClass>(); class A {public : std::shared_ptr<B> b; }; class B {public : std::shared_ptr<A> a; }; std::shared_ptr<A> a = std::make_shared <A>(); std::shared_ptr<B> b = std::make_shared <B>(); a->b = b; b->a = a; class A {public : std::shared_ptr<B> b; }; class B {public : std::weak_ptr<A> a; };
4. 元编程错误 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 template <typename T>class MyClass {}; template <>class MyClass <int > {}; template <typename ... Args>void print (Args... args) { print (args...); } template <typename T>void print (T value) { std::cout << value << std::endl; } template <typename T, typename ... Args>void print (T first, Args... rest) { std::cout << first << " " ; print (rest...); }
5. 并发编程错误 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 std::mutex mtx1, mtx2; void thread1 () { std::lock_guard<std::mutex> lock1 (mtx1) ; std::this_thread::sleep_for (std::chrono::milliseconds (10 )); std::lock_guard<std::mutex> lock2 (mtx2) ; } void thread2 () { std::lock_guard<std::mutex> lock2 (mtx2) ; std::this_thread::sleep_for (std::chrono::milliseconds (10 )); std::lock_guard<std::mutex> lock1 (mtx1) ; } void thread1 () { std::scoped_lock lock (mtx1, mtx2) ; } void thread2 () { std::scoped_lock lock (mtx2, mtx1) ; } std::condition_variable cv; std::mutex mtx; bool ready = false ;void consumer () { cv.wait (std::unique_lock <std::mutex>(mtx)); } void consumer () { std::unique_lock<std::mutex> lock (mtx) ; cv.wait (lock, []{ return ready; }); }
小结 本章介绍了C++中的特殊工具和技术,包括:
类型转换运算符 :static_cast、dynamic_cast、const_cast、reinterpret_cast运行时类型识别(RTTI) :typeid运算符异常处理 :try-catch语句、自定义异常、noexcept说明符内存管理 :智能指针、内存池元编程 :模板特化、模板元编程、可变参数模板并发编程 :线程、互斥量、条件变量、原子操作其他特殊工具 :类型别名、枚举类、内联命名空间、结构化绑定最佳实践 :类型转换、异常处理、内存管理、元编程、并发编程常见错误和陷阱 :类型转换错误、异常处理错误、内存管理错误、元编程错误、并发编程错误这些特殊工具和技术是C++语言的高级特性,它们为程序员提供了更灵活、更强大的编程能力。然而,这些特性也需要谨慎使用,否则可能会导致代码质量下降、性能问题、甚至程序崩溃。在实际编程中,应根据具体情况合理使用这些特性,遵循最佳实践,避免常见错误。
通过本章的学习,读者应该对C++的高级特性有了全面的了解,能够在实际编程中灵活运用这些特性,编写高效、优雅、安全的C++代码。