亚洲国产日韩人妖另类,久久只有这里有精品热久久,依依成人精品视频在线观看,免费国产午夜视频在线

      
      

        C++|以增量開發(fā)的方式逐步自定義一個動態(tài)數(shù)組類

        Be here, we are going to write an integer array class from scratch that implements most of the common functionality that containers should have. This array class is going to be a value container, which will hold copies of the elements it’s organizing. As the name suggests, the container will hold an array of integers, similar to std::vector.

        在這里,我們將從頭開始編寫一個整數(shù)數(shù)組類,該類實現(xiàn)容器應(yīng)該具有的大多數(shù)常見功能。這個數(shù)組類將是一個值容器(指存儲值而不是指針或引用),它將保存它正在組織的元素的副本。顧名思義,容器將保存一個整數(shù)數(shù)組,類似于std::vector。

        First, let’s create the IntArray.h file:

        首先,讓我們創(chuàng)建IntArray.h文件:

        #ifndef INTARRAY_H#define INTARRAY_Hclass IntArray{};#endif

        Our IntArray is going to need to keep track of two values: the data itself, and the size of the array. Because we want our array to be able to change in size, we’ll have to do some dynamic allocation, which means we’ll have to use a pointer to store the data.

        我們的IntArray需要跟蹤兩個值:數(shù)據(jù)本身和數(shù)組的大小。因為我們希望數(shù)組能夠改變大小,所以必須進(jìn)行一些動態(tài)分配,這意味著必須使用指針來存儲數(shù)據(jù)。

        #ifndef INTARRAY_H#define INTARRAY_Hclass IntArray{private: int m_length{}; int* m_data{};};#endif

        Now we need to add some constructors that will allow us to create IntArrays. We are going to add two constructors: one that constructs an empty array, and one that will allow us to construct an array of a predetermined size.

        現(xiàn)在我們需要添加一些構(gòu)造函數(shù)來創(chuàng)建intarray。我們將添加兩個構(gòu)造函數(shù):一個構(gòu)造空數(shù)組,另一個允許我們構(gòu)造預(yù)定大小的數(shù)組。

        #ifndef INTARRAY_H#define INTARRAY_H#include // for assert()class IntArray{private: int m_length{}; int* m_data{};public: IntArray() = default; IntArray(int length): m_length{ length } { assert(length >= 0); if (length > 0) m_data = new int[length]{}; }};#endif

        We’ll also need some functions to help us clean up IntArrays. First, we’ll write a destructor, which simply deallocates any dynamically allocated data. Second, we’ll write a function called erase(), which will erase the array and set the length to 0.

        我們還需要一些函數(shù)來幫助我們清理IntArrays。首先,我們將編寫一個析構(gòu)函數(shù),它只需釋放任何動態(tài)分配的數(shù)據(jù)。其次,我們將編寫一個名為erase()的函數(shù),該函數(shù)將擦除數(shù)組并將長度設(shè)置為0。

        ~IntArray(){ delete[] m_data; // we don’t need to set m_data to null or m_length to 0 here, since the object will be destroyed immediately after this function anyway}void erase(){ delete[] m_data; // We need to make sure we set m_data to nullptr here, otherwise it will // be left pointing at deallocated memory! m_data = nullptr; m_length = 0;}

        Now let’s overload the [] operator so we can access the elements of the array. We should bounds check the index to make sure it’s valid, which is best done using the assert() function. We’ll also add an access function to return the length of the array. Here’s everything so far:

        現(xiàn)在讓我們重載[]操作符,以便訪問數(shù)組的元素。我們應(yīng)該對索引進(jìn)行邊界檢查以確保其有效,這最好使用assert()函數(shù)來完成。我們還將添加一個訪問函數(shù)來返回數(shù)組的長度。以下是目前為止的所有內(nèi)容:

        #ifndef INTARRAY_H#define INTARRAY_H#include // for assert()class IntArray{private: int m_length{}; int* m_data{};public: IntArray() = default; IntArray(int length): m_length{ length } { assert(length >= 0); if (length > 0) m_data = new int[length]{}; } ~IntArray() { delete[] m_data; // we don’t need to set m_data to null or m_length to 0 here, since the object will be destroyed immediately after this function anyway } void erase() { delete[] m_data; // We need to make sure we set m_data to nullptr here, otherwise it will // be left pointing at deallocated memory! m_data = nullptr; m_length = 0; } int& operator[](int index) { assert(index >= 0 && index < m_length); return m_data[index]; } int getLength() const { return m_length; }};#endif

        At this point, we already have an IntArray class that we can use. We can allocate IntArrays of a given size, and we can use the [] operator to retrieve or change the value of the elements.

        此時,我們已經(jīng)有了一個可以使用的IntArray類。我們可以分配給定大小的數(shù)組,并且可以使用[]操作符檢索或更改元素的值。

        However, there are still a few thing we can’t do with our IntArray. We still can’t change its size, still can’t insert or delete elements, and we still can’t sort it.

        然而,對于IntArray,仍然有一些事情我們不能做。我們?nèi)匀粺o法更改其大小,仍然無法插入或刪除元素,仍然無法對其進(jìn)行排序。

        First, let’s write some code that will allow us to resize an array. We are going to write two different functions to do this. The first function, reallocate(), will destroy any existing elements in the array when it is resized, but it will be fast. The second function, resize(), will keep any existing elements in the array when it is resized, but it will be slow.

        首先,讓我們編寫一些代碼來調(diào)整數(shù)組的大小。我們將編寫兩個不同的函數(shù)來實現(xiàn)這一點。第一個函數(shù)reallocation()將在調(diào)整數(shù)組大小時銷毀數(shù)組中的所有現(xiàn)有元素,但速度很快。第二個函數(shù)resize()將在調(diào)整數(shù)組大小時保留數(shù)組中的所有現(xiàn)有元素,但速度較慢。

        // reallocate resizes the array. Any existing elements will be destroyed. This function operates quickly.void reallocate(int newLength){ // First we delete any existing elements erase(); // If our array is going to be empty now, return here if (newLength m_length) ? m_length : newLength }; // Now copy the elements one by one for (int index{ 0 }; index < elementsToCopy; ++index) data[index] = m_data[index]; } // Now we can delete the old array because we don't need it any more delete[] m_data; // And use the new array instead! Note that this simply makes m_data point // to the same address as the new array we dynamically allocated. Because // data was dynamically allocated, it won't be destroyed when it goes out of scope. m_data = data; m_length = newLength;}

        Whew! That was a little tricky!

        呼!這有點棘手!

        Many array container classes would stop here. However, just in case you want to see how insert and delete functionality would be implemented we’ll go ahead and write those too. Both of these algorithms are very similar to resize().

        許多數(shù)組容器類將在此停止。然而,如果您想了解如何實現(xiàn)插入和刪除功能,我們也將繼續(xù)編寫這些內(nèi)容。這兩種算法與resize()非常相似。

        void insertBefore(int value, int index){ // Sanity check our index value assert(index >= 0 && index <= m_length); // First create a new array one element larger than the old array int* data{ new int[m_length+1] }; // Copy all of the elements up to the index for (int before{ 0 }; before < index; ++before) data[before] = m_data[before]; // Insert our new element into the new array data[index] = value; // Copy all of the values after the inserted element for (int after{ index }; after = 0 && index < m_length); // If this is the last remaining element in the array, set the array to empty and bail out if (m_length == 1) { erase(); return; } // First create a new array one element smaller than the old array int* data{ new int[m_length-1] }; // Copy all of the elements up to the index for (int before{ 0 }; before < index; ++before) data[before] = m_data[before]; // Copy all of the values after the removed element for (int after{ index+1 }; after < m_length; ++after) data[after-1] = m_data[after]; // Finally, delete the old array, and use the new array instead delete[] m_data; m_data = data; –m_length;}// A couple of additional functions just for conveniencevoid insertAtBeginning(int value) { insertBefore(value, 0); }void insertAtEnd(int value) { insertBefore(value, m_length); }

        If we want to initialize a array with values, we can do so directly via the initializer list syntax.

        如果要使用值初始化數(shù)組,可以直接通過初始化列表語法進(jìn)行初始化。

        The IntArray class also can have a constructor with an initializer list.

        IntArray類還可以具有具有初始化列表的構(gòu)造函數(shù)。

        As a result, std::initializer_list can be used to implement constructors, assignment operators, and other functions that accept a list initialization parameter. std::initailizer_list lives in the header.

        因此,std::initializer_list可用于實現(xiàn)構(gòu)造函數(shù)、賦值運算符和其他接受列表初始化參數(shù)的函數(shù)。std::initializer_list位于頭文件中。

        IntArray(std::initializer_list list) // allow IntArray to be initialized via list initialization: IntArray(static_cast(list.size())) // use delegating constructor to set up initial array{// Now initialize our array from the listint count{ 0 };for (auto element : list){m_data[count] = element;++count;}}

        Here is our IntArray container class in its entirety.

        這是我們的IntArray容器類的全部內(nèi)容。

        IntArray.h:

        #ifndef INTARRAY_H#define INTARRAY_H#include // for assert()class IntArray{private: int m_length{}; int* m_data{};public: IntArray() = default; IntArray(int length): m_length{ length } { assert(length >= 0); if (length > 0) m_data = new int[length]{}; }IntArray(std::initializer_list list) // allow IntArray to be initialized via list initialization: IntArray(static_cast(list.size())) // use delegating constructor to set up initial array{// Now initialize our array from the listint count{ 0 };for (auto element : list){m_data[count] = element;++count;}} ~IntArray() { delete[] m_data; // we don’t need to set m_data to null or m_length to 0 here, since the object will be destroyed immediately after this function anyway } void erase() { delete[] m_data; // We need to make sure we set m_data to nullptr here, otherwise it will // be left pointing at deallocated memory! m_data = nullptr; m_length = 0; } int& operator[](int index) { assert(index >= 0 && index < m_length); return m_data[index]; } // reallocate resizes the array. Any existing elements will be destroyed. This function operates quickly. void reallocate(int newLength) { // First we delete any existing elements erase(); // If our array is going to be empty now, return here if (newLength m_length) ? m_length : newLength }; // Now copy the elements one by one for (int index{ 0 }; index = 0 && index <= m_length); // First create a new array one element larger than the old array int* data{ new int[m_length+1] }; // Copy all of the elements up to the index for (int before{ 0 }; before < index; ++before) data[before] = m_data[before]; // Insert our new element into the new array data[index] = value; // Copy all of the values after the inserted element for (int after{ index }; after = 0 && index < m_length); // If we're removing the last element in the array, we can just erase the array and return early if (m_length == 1) { erase(); return; } // First create a new array one element smaller than the old array int* data{ new int[m_length-1] }; // Copy all of the elements up to the index for (int before{ 0 }; before < index; ++before) data[before] = m_data[before]; // Copy all of the values after the removed element for (int after{ index+1 }; after < m_length; ++after) data[after-1] = m_data[after]; // Finally, delete the old array, and use the new array instead delete[] m_data; m_data = data; –m_length; } // A couple of additional functions just for convenience void insertAtBeginning(int value) { insertBefore(value, 0); } void insertAtEnd(int value) { insertBefore(value, m_length); } int getLength() const { return m_length; }};#endif

        Now, let’s test it just to prove it works:

        現(xiàn)在,讓我們測試一下,以證明它是有效的:

        #include #include “IntArray.h”int main(){ // Declare an array with 10 elements IntArray array(10); // Fill the array with numbers 1 through 10 for (int i{ 0 }; i<10; ++i) array[i] = i+1; // Resize the array to 8 elements array.resize(8); // Insert the number 20 before element with index 5 array.insertBefore(20, 5); // Remove the element with index 3 array.remove(3); // Add 30 and 40 to the end and beginning array.insertAtEnd(30); array.insertAtBeginning(40); // Print out all the numbers for (int i{ 0 }; i

        This produces the result:

        40 1 2 3 5 20 6 7 8 30

        Although writing container classes can be pretty complex, the good news is that you only have to write them once. Once the container class is working, you can use and reuse it as often as you like without any additional programming effort required.

        盡管編寫容器類可能相當(dāng)復(fù)雜,但好消息是您只需編寫一次。一旦容器類開始工作,您就可以隨時使用和重用它,而無需進(jìn)行任何額外的編程工作。

        It is also worth explicitly mentioning that even though our sample IntArray container class holds a built-in data type (int), we could have just as easily used a user-defined type (e.g. a Point class).

        還值得一提的是,即使我們的示例IntArray容器類包含內(nèi)置數(shù)據(jù)類型(int),我們也可以同樣輕松地使用用戶定義的類型(例如Point類)。

        One more thing: If a class in the standard library meets your needs, use that instead of creating your own. For example, instead of using IntArray, you’re better off using std::vector. It’s battle tested, efficient, and plays nicely with the other classes in the standard library. But sometimes you need a specialized container class that doesn’t exist in the standard library, so it’s good to know how to create your own when you need to. We’ll talk more about containers in the standard library once we’ve covered a few more fundamental topics.

        還有一件事:如果標(biāo)準(zhǔn)庫中的類滿足您的需要,請使用它,而不是創(chuàng)建自己的類。例如,與其使用IntArray,不如使用std::vector。它經(jīng)過了嚴(yán)格測試,效率很高,并且與標(biāo)準(zhǔn)庫中的其他類配合得很好。但有時您需要一個標(biāo)準(zhǔn)庫中不存在的專用容器類,因此最好知道如何在需要時創(chuàng)建自己的容器類。一旦我們涵蓋了一些更基本的主題,我們將進(jìn)一步討論標(biāo)準(zhǔn)庫中的容器。

        ref

        16.6 — Container classes

        -End-

        鄭重聲明:本文內(nèi)容及圖片均整理自互聯(lián)網(wǎng),不代表本站立場,版權(quán)歸原作者所有,如有侵權(quán)請聯(lián)系管理員(admin#wlmqw.com)刪除。
        上一篇 2022年6月16日 21:22
        下一篇 2022年6月16日 21:23

        相關(guān)推薦

        聯(lián)系我們

        聯(lián)系郵箱:admin#wlmqw.com
        工作時間:周一至周五,10:30-18:30,節(jié)假日休息