<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      C++11

      類型推導

      類型推導是C++的一種特性,允許編譯器自動推導變量的類型,而不需要顯式地制定類型。

      auto

      auto用于讓編譯器自動推導變量類型,常見用法:

      1. 基本示例:
      auto x = 10;
      
      1. 與容器一起使用:
      vector<string> names = { "Alice", "Bob"};
      for (auto it = names.begin(); it != names.end(); it++) {
          cout << *it;
      }
      
      1. 與函數返回類型一起使用:
      auto add(int a, int b) {
          return a+b;
      }
      
      1. 與for循環一起使用:
      for (const auto & name : names) {}
      

      decltype

      decltype關鍵字用于獲取表達式類型。通常用于模版編程和復雜類型推導:

      int a = 10;
      decltype(a) b = 11;
      

      拖尾返回類型

      拖尾返回類型是一種在函數聲明中指定函數返回類型的方式,通常與auto關鍵字結合使用。它在函數參數列表之后使用‘->’引出返回類型。

      auto add(int a, int b) -> int {
          return a+b;
      }
      
      template<typename T, typename U>
      auto add(T x, U y) -> decltype(x+y) {
          return x+y;
      }
      

      lambda

      在C++中,lambda表達式是一種匿名函數,可以在代碼中定義并立即使用。它們非常適合用于短小的回調函數或臨時函數對象。

      基本語法:

      [capture list] (parameter list) option -> return type { function body}
      

      capture list:捕獲子句,定義lambda表達式可以訪問的外部變量。

      [] :不捕獲外部變量
      [=]:按值捕獲所有外部變量
      [&]:按引用捕獲所有外部變量
      [a]:按值捕獲變量a
      [&a]:按引用捕獲變量a
      [a, &]:按值捕獲變量a,按引用捕獲其他變量

      parameter list:參數列表,與普通函數相同
      option:是函數選項;可以填 mutable,exception,attribute。(選填)

      mutable說明lambda表達式體內的代碼可以修改被捕獲的變量,并且可以訪問被捕獲的對象的non-const方法。
      exception說明lambda表達式是否拋出異常以及何種異常。
      attribute用來聲明屬性。

      return type:返回類型,通常情況下,編譯器可以自動推斷出lambda表達式的返回類型,因此不需要顯式的指出,但是,在一些復雜的情況下,例如條件語句,編譯器可能無法確定返回類型,此時需要顯式的指定返回類型。

      lambda表達式中的捕獲變量是在lambda定義時進行的,也就是說,當lambda被定義時,對于每個lambda捕獲的變量,都會在lambda內部創建一個同名的克隆變量,這些克隆變量在此時就從同名的外部變量中初始化。

      使用引用捕獲可能會導致一些潛在的問題,主要有以下兩點:

      引用懸掛:如果捕獲的引用的生命周期比lambda表達式的生命周期要短,那么當lambda表達式被調用時,引用可能已經失效,這將導致未定義的行為。

      std::function<void()> createLambda() {
      int x = 5;
      return [&x]() { cout << x; };
      }
      

      數據競爭:如果多個線程同時訪問和修改同一個變量,而沒有適當的同步機制,就會發生數據競爭。如果在lambda中通過引用捕獲這個變量,并在多線程中使用這個lambda,就可能發生這種情況。

      int x = 5;
      auto lambda = [&x]() { ++x; };
      thread t1(lambda);
      thread t2{lambda);
      t1.join();
      t2.join();
      

      智能指針

      C++11 引入三種智能指針:unique_ptr<T>,shared_ptr<T>,weak_ptr<T>。這些智能指針的主要目的是自動管理動態分配的內存,以防止內存泄漏。

      unique_ptr<T>

      unique_ptr<T>是一種獨占所有權的智能指針,當其離開作用域時會自動釋放所擁有的對象。

      {
          unique_ptr<int> uptr = make_unique<int>(200);
          //離開uptr的作用域時會自動釋放內存
      }
      

      unique_ptr可以賦值給其他unique_ptr,但是這個過程實際上是轉移所有權,而不是復制所有權。這意味著一旦一個unique_ptr被賦值給另外一個unique_ptr,原來的unique_ptr將失去所有權,變為空指針。
      如果想要將一個unique_ptr賦值給一個原始指針,可以使用get()成員函數獲取unique_ptr的原始指針。但是需要注意,這并不會改變unique_ptr的所有權,當unique_ptr被銷毀時,它仍然后釋放其所擁有的對象,即使有其他原始指針正指向它。

      unique_ptr的常見用法:

      1. 動態內存管理:unique_ptr可以實現自動管理動態分配的內存,防止內存泄漏。
      unique_ptr<int> uptr(new int(5));//the int object will automatically deleted when uptr is out of scope
      
      1. 實現獨占所有權語義:unique_ptr可以用于實現需要獨占所有權的數據結構或者算法。
      class NoSharedData {
          unique_ptr<int> data;
      public:
          NoSharedData(int value) : data(new int(value)) {}
          //copy constructor and copy assignment operator are implicitly deleted
      }
      

      3.工廠函數:如果一個函數要返回一個新創建的對象,那么可以返回一個unique_ptr,以明確表示這個對象的所有權已經轉移給調用者。

      unique_ptr<int> createInt(int value) {
          return unique_ptr<int>(new int(value));
      }
      
      1. Pimpl慣用法:Pimpl慣用法是一種隱藏類的實現細節的技術,通常使用unique_ptr來實現。
      class MyClass {
      public:
          MyClass();
          ~MyClass();
          //other public member functions
      private:
          class Impl;
          unique_ptr<Impl> pimpl;
      };
      
      1. 自定義刪除器:unique_ptr可以使用自定刪除器來處理特殊的資源清理需求,例如,管理打開的文件或鎖,當unique_ptr銷毀時,文件被關閉或鎖被釋放。
      unique_ptr<FILE, decltype(&fclose)> fp(fopen("test.txt", "r"), &fclose);
      

      注意:unique_ptr不可以被復制,但是可以被移動??梢允褂胹td::move來轉移一個unique_ptr所擁有的對象所有權。

      shared_ptr<T>

      shared_ptr是一種共享所有權的智能指針,它使用引用計數來跟蹤有過少個shared_ptr共享同一個對象。當最后一個shared_ptr被銷毀時,它會自動釋放其所指向的對象。
      shared_ptr引用計數是原子操作,可以保證線程安全,但是shared_ptr指向的對象并不保證線程安全。更多使用建議CSDN

      weak_ptr<T>

      weak_ptr是一種智能指針,它持有對由shared_ptr管理的對象的非擁有(“弱”)引用。它必須轉換為shared_ptr才能訪問引用的對象(lock())。weak_ptr模擬臨時所有權:當一個對象只需要在存在時被訪問,并且它可能在任何時候被刪除。

      weak_ptr可以解決懸掛指針問題。使用原始指針,我們無法知道數據是否已經被釋放。相反,通過讓shared_ptr管理數據,并向數據的用戶提供weak_ptr,用戶可以通過調用expired()和lock()來檢查數據的有效性。

      int main()
      {
          shared_ptr<int> sptr;
          //接管指針
          sptr.reset(new int);
          *sptr = 10;
          weak_ptr<int> w1 = sptr;
          //刪除管理對象,獲取新指針
          sptr.reset(new int);
          *sptr = 20;
          weak_ptr<int> w2 = sptr;
          //w1 已經過期
          if ( auto tmp = w1.lock() ) {
              cout << "w1 value is " << *tmp;
          }
          if (auto. tmp = w2.lock() ) {
              cout << "w2 value is " << *tmp;
          }
      }
      

      weak_ptr還可以解決shared_ptr相互引用產生死鎖的問題。

      class B;
      class A {
      public:
          void setB(shared_ptr<B> b) { b_ptr = b; }
          void show() {
              if (auto b = b_ptr.lock()) {
                  cout << "A has a reference to B";
              } else {
                  cout << "B is destroyed";
              }
           }
           ~A() { cout << "~A"; }
      private:
          weak_ptr<B> b_ptr;
      };
      
      class B {
       public:
          void setA(shared_ptr<A> a) { a_ptr = a; }
          void show() {
              if (auto a = a_ptr.lock()) {
                 cout << "B has a reference to A";
              } else {
                 cout << "A is destroyed";
              }
           }
           ~B() { cout << "~B"; }
      private:
          weak_ptr<A> A_ptr;
      };
      
      int main()
      {
          auto a = make_shared<A>();
          auto b = make_shared<B>();
          a->setB(b);
          b->setA(a);
          a->show();
          b->show();
          return 0;
      }
      

      右值引用

      右值引用是C++11引入的新特性,用于實現移動語義和完美轉發。右值引用允許我們區分左值和右值,從而優化資源管理和性能。

      左值:表示一個有名字的、可持久存在的對象;
      右值:表示一個臨時對象或將要被銷毀的對象;

      右值引用使用 && 語法,可以綁定到右值,從而實現移動語義。

      一、右值引用的作用

      • 實現移動語義
        在 C++ 中,拷貝構造函數和賦值運算符通常用于對象的復制操作。但對于一些包含大量資源(如動態分配的內存、文件句柄等)的對象,復制操作可能非常耗時和消耗資源。
        右值引用允許實現移動構造函數和移動賦值運算符,這些函數可以將資源從一個即將被銷毀的對象(右值)轉移到新對象中,而不是進行傳統的復制操作,從而提高性能。
        例如,對于一個自定義的字符串類,如果沒有移動語義,當進行字符串賦值操作時,可能會進行大量的內存復制。而使用右值引用實現移動賦值運算符后,可以直接將源字符串的內存指針轉移到目標字符串,避免不必要的復制。
         class ResourceManager {
         private:
             int* data;
         public:
             ResourceManager() : data(new int[1000]) { }
             ~ResourceManager() { delete[] data; }
             ResourceManager(const ResourceManager& other) : data(new int[1000]) {
                 std::copy(other.data, other.data + 1000, data);
             }
             ResourceManager(ResourceManager&& other) noexcept : data(other.data) {
                 other.data = nullptr;
             }
             ResourceManager& operator=(ResourceManager&& other) noexcept {
                 if (this!= &other) {
                     delete[] data;
                     data = other.data;
                     other.data = nullptr;
                 }
                 return *this;
             }
         };
      
      • 完美轉發
        完美轉發是指函數模板能夠將自己的參數 “完美” 地轉發給另一個函數,保持參數的左值 / 右值屬性不變。
        通過右值引用和模板參數推導,可以實現完美轉發。這在泛型編程中非常有用,例如在函數模板中,可以根據參數的實際類型決定是進行復制還是移動操作。
      #include <iostream>
      #include <utility>
      
      template<typename T>
      void func(T&& arg) {
          anotherFunc(std::forward<T>(arg));
      }
      
      void anotherFunc(int& x) {
          std::cout << "Called with lvalue reference." << std::endl;
      }
      
      void anotherFunc(int&& x) {
          std::cout << "Called with rvalue reference." << std::endl;
      }
      
      int main() {
          int a = 10;
          func(a); // 傳入左值,調用 anotherFunc 的左值引用版本
          func(20); // 傳入右值,調用 anotherFunc 的右值引用版本
          return 0;
      }
      

      二、右值的分類

      • 純右值
        包括字面量、臨時對象等。例如,int i = 42;中的42是純右值,std::string s1 = "hello"; std::string s2 = s1 + " world";中的s1 + " world"也是純右值,它是一個臨時的字符串對象。
      • 將亡值
        即將被銷毀的對象,可以通過右值引用捕獲并延長其生命周期。例如,std::vectorstd::string v1{"a", "b", "c"}; std::vectorstd::string v2 = std::move(v1);這里的v1在被std::move轉換后成為將亡值,可以被右值引用捕獲,觸發移動構造函數,將v1的資源轉移到v2。

      三、使用右值引用的注意事項

      • 右值引用只能綁定到右值,不能綁定到左值。但通過std::move可以將左值轉換為右值引用。
      • 移動操作可能會使被移動的對象處于未定義狀態,除非對象明確支持多次移動。在使用移動后的對象時,需要注意其狀態可能已經改變。
      • 右值引用和左值引用可以重載函數,但在調用時需要根據參數的類型來確定調用哪個版本。

      多線程

      Thread

      C++11 引入了std::thread提供線程的創建和管理的函數或類的接口。

      #include <iostream>
      #include <thread>
      
      void printNumber(int num) {
          std::cout << "Number: " << num << std::endl;
      }
      
      int main() {
          int number = 42;
          std::thread t(printNumber, number);
          t.join();
          return 0;
      }
      

      mutex

      C++11 新增<mutex>支持互斥鎖,保護資源共享。

      #include <iostream>
      #include <thread>
      #include <mutex>
      
      std::mutex mutex1;
      int counter = 0;
      
      void incrementCounter() {
          for (int i = 0; i < 1000; ++i) {
              std::lock_guard<std::mutex> guard(mutex1);
              counter++;
          }
      }
      
      int main() {
          std::thread t1(incrementCounter);
          std::thread t2(incrementCounter);
          t1.join();
          t2.join();
          std::cout << "Counter: " << counter << std::endl;
          return 0;
      }
      

      condition_variable

      C++11新增<condition_variable>提供條件變量功能,支持多線程之間同步。

      #include <iostream>
      #include <thread>
      #include <mutex>
      #include <condition_variable>
      
      std::mutex mutex2;
      std::condition_variable cv;
      bool ready = false;
      
      void waitingThread() {
          std::unique_lock<std::mutex> lock(mutex2);
          while (!ready) {
              cv.wait(lock);
          }
          std::cout << "Waiting thread notified." << std::endl;
      }
      
      void notificationThread() {
          std::this_thread::sleep_for(std::chrono::seconds(2));
          {
              std::lock_guard<std::mutex> lock(mutex2);
              ready = true;
          }
          cv.notify_one();
          std::cout << "Notification thread sent notification." << std::endl;
      }
      
      int main() {
          std::thread t1(waitingThread);
          std::thread t2(notificationThread);
          t1.join();
          t2.join();
          return 0;
      }
      

      atomic

      c++11新增<atomic>支持原子操作。std::atomic可以用于各種基本數據類型,如int、bool、double等。

      #include <iostream>
      #include <atomic>
      #include <thread>
      
      std::atomic<int> counter(0);
      std::atomic<bool> flag(false);
      std::atomic<double> value(0.0);
      
      void incrementCounter() {
          for (int i = 0; i < 1000; ++i) {
              counter++;
          }
      }
      
      int main() {
          std::thread t1(incrementCounter);
          std::thread t2(incrementCounter);
      
          t1.join();
          t2.join();
      
          std::cout << "Counter value: " << counter << std::endl;
      
          return 0;
      }
      
      

      原子操作的方法:(cppreference)

      • load():以原子方式讀取當前值。
      • store():以原子方式存儲一個新值。
      • exchange():以原子方式將當前值替換為新值,并返回舊值。
      • compare_exchange_weak()和compare_exchange_strong():比較并交換操作,如果當前值等于預期值,則將其替換為新值。
      std::atomic<int> num(10);
      
      int oldValue = num.load();
      num.store(20);
      
      int newValue = num.exchange(30);
      std::cout << "Old value: " << oldValue << ", New value: " << newValue << std::endl;
      
      bool success = num.compare_exchange_strong(oldValue, 40);
      std::cout << "Success: " << success << ", Current value: " << num << std::endl;
      

      future

      在 C++ 中,<future>頭文件提供了用于異步操作的工具。它允許你啟動一個異步任務,并在將來的某個時間獲取其結果。

      std::promise:可以用來設置一個值或異常,供與之關聯的std::future對象獲取。

         #include <iostream>
         #include <future>
      
         void setValue(std::promise<int>& p) {
             p.set_value(42);
         }
      
         int main() {
             std::promise<int> prom;
             std::future<int> fut = prom.get_future();
      
             std::thread t(setValue, std::ref(prom));
      
             int value = fut.get();
             std::cout << "Value: " << value << std::endl;
      
             t.join();
             return 0;
         }
      

      std::future:用于獲取異步操作的結果??梢酝ㄟ^get()方法阻塞等待結果,也可以使用wait()、wait_for()和wait_until()方法進行非阻塞等待。

      異步函數(std::async)

      std::async函數啟動一個異步任務,并返回一個std::future對象,用于獲取任務的結果。

         #include <iostream>
         #include <future>
      
         int add(int a, int b) {
             return a + b;
         }
      
         int main() {
             std::future<int> fut = std::async(add, 10, 20);
      
             int result = fut.get();
             std::cout << "Result: " << result << std::endl;
      
             return 0;
         }
      

      如果異步任務拋出異常,這個異??梢酝ㄟ^std::future的get()方法傳播到調用者線程。

         #include <iostream>
         #include <future>
      
         void throwException() {
             throw std::runtime_error("An error occurred.");
         }
      
         int main() {
             std::future<void> fut = std::async(throwException);
      
             try {
                 fut.get();
             } catch (const std::exception& e) {
                 std::cout << "Caught exception: " << e.what() << std::endl;
             }
      
             return 0;
         }
      

      參考:
      C++11 中文
      C++11 博客園
      右值引用 博客園

      posted on 2024-08-24 18:08  zc32  閱讀(45)  評論(0)    收藏  舉報

      導航

      主站蜘蛛池模板: 天堂网av一区二区三区| 99精品国产一区二区三区| 国产午夜精品福利视频| 亚洲乱码中文字幕小综合| 艳妇臀荡乳欲伦69调教视频| 精品国产成人网站一区在线| 国产av亚洲精品ai换脸电影| 人妻日韩人妻中文字幕| 久久精品不卡一区二区| 吉安县| 亚洲国产精品久久久天堂麻豆宅男 | 林芝县| 色九九视频| 国产精品户外野外| 天堂资源国产老熟女在线| 高潮潮喷奶水飞溅视频无码| 久久国产福利播放| 久久国产精品久久精品国产| 国产精品三级中文字幕| 武宣县| 成人亚洲av免费在线| 免费av深夜在线观看| 成人国产av精品免费网| 精品亚洲欧美中文字幕在线看| 久久香蕉国产线看观看猫咪av| 亚洲国产一区二区三区| 亚洲嫩模一区二区三区| 精品人妻中文字幕av| 色情一区二区三区免费看| 国产成人午夜福利在线观看| 美日韩av一区二区三区| 亚洲色大成网站www久久九九| 欧美性猛交xxxx乱大交丰满| 一区二区三区四区五区自拍| 亚洲av精彩一区二区| 欧美啪啪网| 国产一区二区亚洲精品| 偷窥少妇久久久久久久久| 国产一区在线播放无遮挡| 国产亚洲视频免费播放| 中文字幕av一区二区|