<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                按值傳遞的意義是什么?? 當一個函數的參數按值傳遞時,這就會進行拷貝。當然,編譯器懂得如何去拷貝。? 而對于我們自定義的類型,我們也許需要提供拷貝構造函數。 但是不得不說,拷貝的代價是昂貴的。 所以我們需要尋找一個避免不必要拷貝的方法,即C++11提供的移動語義。? 上一篇博客中有一個句話用到了: ~~~ #include <iostream> void f(int& i) { std::cout << "lvalue ref: " << i << "\n"; } void f(int&& i) { std::cout << "rvalue ref: " << i << "\n"; } int main() { int i = 77; f(i); // lvalue ref called f(99); // rvalue ref called f(std::move(i)); // 稍后介紹 return 0; } ~~~ 實際上,右值引用主要用于創建移動構造函數和移動賦值運算。 移動構造函數類似于拷貝構造函數,把類的實例對象作為參數,并創建一個新的實例對象。? 但是 移動構造函數可以避免**內存的重新分配**,因為我們知道右值引用提供了一個暫時的對象,而不是進行copy,所以我們可以進行移動。 換言之,在設計到關于臨時對象時,右值引用和移動語義允許我們避免不必要的拷貝。我們不想拷貝將要消失的臨時對象,所以這個臨時對象的資源可以被我們用作于其他的對象。 右值就是典型的臨時變量,并且他們可以被修改。如果我們知道一個函數的參數是一個右值,我們可以把它當做一個臨時存儲。這就意味著我們要移動而不是拷貝右值參數的內容。這就會節省很多的空間。 說多無語,看代碼: ~~~ #include <iostream> #include <algorithm> class A { public: // Simple constructor that initializes the resource. explicit A(size_t length) : mLength(length), mData(new int[length]) { std::cout << "A(size_t). length = " << mLength << "." << std::endl; } // Destructor. ~A() { std::cout << "~A(). length = " << mLength << "."; if (mData != NULL) { std::cout << " Deleting resource."; delete[] mData; // Delete the resource. } std::cout << std::endl; } // Copy constructor. A(const A& other) : mLength(other.mLength), mData(new int[other.mLength]) { std::cout << "A(const A&). length = " << other.mLength << ". Copying resource." << std::endl; std::copy(other.mData, other.mData + mLength, mData); } // Copy assignment operator. A& operator=(const A& other) { std::cout << "operator=(const A&). length = " << other.mLength << ". Copying resource." << std::endl; if (this != &other) { delete[] mData; // Free the existing resource. mLength = other.mLength; mData = new int[mLength]; std::copy(other.mData, other.mData + mLength, mData); } return *this; } // Move constructor. A(A&& other) : mData(NULL), mLength(0) { std::cout << "A(A&&). length = " << other.mLength << ". Moving resource.\n"; // Copy the data pointer and its length from the // source object. mData = other.mData; mLength = other.mLength; // Release the data pointer from the source object so that // the destructor does not free the memory multiple times. other.mData = NULL; other.mLength = 0; } // Move assignment operator. A& operator=(A&& other) { std::cout << "operator=(A&&). length = " << other.mLength << "." << std::endl; if (this != &other) { // Free the existing resource. delete[] mData; // Copy the data pointer and its length from the // source object. mData = other.mData; mLength = other.mLength; // Release the data pointer from the source object so that // the destructor does not free the memory multiple times. other.mData = NULL; other.mLength = 0; } return *this; } // Retrieves the length of the data resource. size_t Length() const { return mLength; } private: size_t mLength; // The length of the resource. int* mData; // The resource. }; ~~~ **移動構造函數**? 語法: ~~~ A(A&& other) noexcept // C++11 - specifying non-exception throwing functions { mData = other.mData; // shallow copy or referential copy other.mData = nullptr; } ~~~ 最主要的是沒有用到新的資源,是移動而不是拷貝。? 假設一個地址指向了一個有一百萬個int元素的數組,使用move構造函數,我們沒有創造什么,所以代價很低。 ~~~ // Move constructor. A(A&& other) : mData(NULL), mLength(0) { // Copy the data pointer and its length from the // source object. mData = other.mData; mLength = other.mLength; // Release the data pointer from the source object so that // the destructor does not free the memory multiple times. other.mData = NULL; other.mLength = 0; } ~~~ **移動比拷貝更快!!!** **移動賦值運算符**? 語法: ~~~ A& operator=(A&& other) noexcept { mData = other.mData; other.mData = nullptr; return *this; } ~~~ 工作流程這樣的:Google上這么說的: Release any resources that *this currently owns.? Pilfer other’s resource.? Set other to a default state.? Return *this. ~~~ // Move assignment operator. A& operator=(A&& other) { std::cout << "operator=(A&&). length = " << other.mLength << "." << std::endl; if (this != &other) { // Free the existing resource. delete[] mData; // Copy the data pointer and its length from the // source object. mData = other.mData; mLength = other.mLength; // Release the data pointer from the source object so that // the destructor does not free the memory multiple times. other.mData = NULL; other.mLength = 0; } return *this; } ~~~ 讓我們看幾個move帶來的好處吧!? vector眾所周知,C++11后對vector也進行了一些優化。例如vector::push_back()被定義為了兩種版本的重載,一個是cosnt T&左值作為參數,一個是T&&右值作為參數。例如下面的代碼: ~~~ std::vector<A> v; v.push_back(A(25)); v.push_back(A(75)); ~~~ 上面兩個push_back()都會調用push_back(T&&)版本,因為他們的參數為右值。這樣提高了效率。 而 當參數為左值的時候,會調用push_back(const T&) 。 ~~~ #include <vector> int main() { std::vector<A> v; A aObj(25); // lvalue v.push_back(aObj); // push_back(const T&) } ~~~ 但事實我們可以使用 static_cast進行強制: ~~~ // calls push_back(T&&) v.push_back(static_cast<A&&>(aObj)); ~~~ 我們可以使用std::move完成上面的任務: ~~~ v.push_back(std::move(aObj)); //calls push_back(T&&) ~~~ 似乎push_back(T&&)永遠是最佳選擇,但是一定要記住:? push_back(T&&) 使得參數為空。如果我們想要保留參數的值,我們這個時候需要使用拷貝,而不是移動。 最后寫一個例子,看看如何使用move來交換兩個對象: ~~~ #include <iostream> using namespace std; class A { public: // constructor explicit A(size_t length) : mLength(length), mData(new int[length]) {} // move constructor A(A&& other) { mData = other.mData; mLength = other.mLength; other.mData = nullptr; other.mLength = 0; } // move assignment A& operator=(A&& other) noexcept { mData = other.mData; mLength = other.mLength; other.mData = nullptr; other.mLength = 0; return *this; } size_t getLength() { return mLength; } void swap(A& other) { A temp = move(other); other = move(*this); *this = move(temp); } int* get_mData() { return mData; } private: int *mData; size_t mLength; }; int main() { A a(11), b(22); cout << a.getLength() << ' ' << b.getLength() << endl; cout << a.get_mData() << ' ' << b.get_mData() << endl; swap(a,b); cout << a.getLength() << ' ' << b.getLength() << endl; cout << a.get_mData() << ' ' << b.get_mData() << endl; return 0; } ~~~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看