簡體   English   中英

C ++-在期望類型為Iterator的向量(或其他容器)構造函數中使用數組/指針。 那怎么可能?

[英]C++ - Using array/pointers in vector (or other container) constructor that expects type Iterator. How is that possible?

下面的文字來自C ++在線課程。 它說vector類的構造函數

 template <class InputIterator>
          vector ( InputIterator first, InputIterator last, const Allocator& = Allocator() );

可以接收指針作為第一個( InputIterator first )和第二個參數( InputIterator last )。

下一個構造函數使用迭代器進行初始化。 它將創建一個向量,該向量具有從第一個(包含)到最后一個(不含)的值的副本。 在最典型的情況下,此構造函數使用現有集合中的元素創建新的向量。 但是由於將迭代器定義為一組操作而不是某種類型的事實,因此也可以使用普通指針。 此評論得出一個結論,您可以使用普通的C ++數組初始化集合。 實際上,您可以。

#include <vector>
#include <iostream>

using namespace std;

int main()
{
    int a1[]={1,2,3,4,5,6,7,8,9,10};
    //first one
    vector<int> v1(a1, a1+10);
    cout<<"Size (v1):  "<<v1.size()<<endl;
    for(unsigned i = 0; i < v1.size(); ++i)
    {
        cout<< v1[i]<<" ";
    }
    cout<<endl;
    //second one;
    vector<int> v2(a1+5,a1+10);
    cout<<"Size (v2):  "<<v2.size()<<endl;
    for(unsigned i = 0; i < v2.size(); ++i)
    {
        cout<< v2[i]<<" ";
    }
    cout<<endl;
    return 0;
}

我可以習慣這一點,但是我真的不明白為什么有這種可能。 我想了解這項技術。

在這種情況下(請參見代碼),我的問題是,我怎么可能只簡單地放置一個數組地址而不是一個迭代器?

在上面的代碼中,將一個int *類型的元素作為InputIterator類型的參數。 這使我感到困惑。

所有的故事都是關於構造對迭代器的期望。 它期望能夠增加它(使用++),以尊重它(使用*)。 插入器既可以是重載++和*運算符的類,也可以是自然支持這兩種操作的基本指針類型。

實際上,C ++迭代器經過了精心設計,以概括指針的語義並模仿其語法(因此, operator*重載)。

請參閱原始SGI文檔中的一般性討論或此處的最新C ++版本的處理,並特別注意:

  1. 指針滿足RandomAccessIterators的所有要求
  2. RandomAccessIterators為InputIterator需求的超集建模
  3. std::vector構造函數僅需要InputIterator

如果您真的不相信#1,那么您可能還希望看到標准庫顯式地為原始指針提供迭代器特征 ,並且如果您仍在苦苦掙扎,請看一下構造函數的實現,以及請放心,針對其參數的所有操作格式都正確。

要回答最后一個問題,指針指向內存中的位置。 由於存儲器是隨機訪問的,因此指針可以歸類為具有隨機訪問的指針。 迭代器具有相同的分類類型。 cplusplus.com的布局很好,可以顯示此處支持哪種類型的迭代器。 這樣,我們可以看到輸入迭代器是最低的類型,並且它們可以執行最少的操作。 由於指針與隨機訪問迭代器相同,並且隨機訪問迭代器可以執行輸入迭代器可以執行的所有操作,因此沒有任何問題。

如果這是相反的方法,並且您有一個需要隨機訪問迭代器的函數,並且提供了前向迭代器,則不能保證代碼會正常工作。 這是因為該函數可能依賴於某個操作,而隨機訪問迭代器可以執行此操作,而正向迭代器則無法執行。

通常,當您編寫這種類型的代碼並指定所需的迭代器類型時,可以指定允許代碼編譯的最小類型。 只是打印內容的東西只需要一個正向迭代器,因為您只是遍歷需要隨機訪問的內容時。

因為數組將其元素存儲在連續內存中。 因此,如果您知道類型的大小以及第一個元素的指針,則可以找出所有其余元素的地址。

int values[10];
&values[5] == &values[0] + 5 // due to pointer arithmetic

§5.7加法運算符

加法運算符+和-從左到右分組。 通常對算術或枚舉類型的操作數執行算術轉換。

另外 ,兩個操作數都應具有算術或無作用域枚舉類型,或者一個操作數應是指向完全定義的對象類型的指針另一個操作數應具有整數或無作用域的枚舉類型

對於減法,應滿足下列條件之一:
—兩個操作數都具有算術或非范圍枚舉類型; 要么
—兩個操作數都是相同完全定義對象類型的cv限定或cv非限定版本的指針; 要么
—左操作數是指向完全定義的對象類型的指針,而右操作數具有整數或無作用域的枚舉類型。

...

當將具有整數類型的表達式添加到指針或從指針中減去時,結果將具有指針操作數的類型。 如果指針操作數指向數組對象的元素,並且數組足夠大,則結果指向與原始元素偏移的元素,以使結果數組元素和原始數組元素的下標之差等於整數表達式 換句話說,如果表達式P指向數組對象的第i個元素,則表達式(P)+ N(相當於N +(P))和(P)-N(其中N的值為n)表示分別存在於數組對象的第i + n個元素和第i-n個元素中,前提是它們存在。 此外,如果表達式P指向數組對象的最后一個元素,則表達式(P)+1指向數組對象的最后一個元素之后,如果表達式Q指向數組對象的最后一個元素之后,表達式(Q)-1指向數組對象的最后一個元素。 如果指針操作數和結果都指向同一數組對象的元素,或者指向數組對象的最后一個元素,則求值不會產生溢出; 否則,行為是不確定的。

因此,基本上,該標准定義了指針T*和整數類型之間的算術

T* t + n  // where n is an offset (of integral type)

從初始t得出另一個n * sizeof(T) T*

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM