2017-01-31 112 views
2

我想使用C++數組的迭代器,但也使用原始指針。 我可以用一個靜態的載體做:stl ::與原始指針的迭代器

#define SIZE 10 
int vect[SIZE] = {0}; 
vect[3] = 5; 
int* p = std::find(std::begin(vect), std::end(vect), 5); 
bool success = p != std::end(vect); 

怎麼可能與原始指針(也許堆上分配向量)辦呢? 當然,編譯器不知道數據的大小,因此,這段代碼

int* pStart = vect; 
std::find(std::begin(pStart), std::end(pStart), 5); 

error C2784: '_Ty *std::begin(_Ty (&)[_Size])' : 
could not deduce template argument for '_Ty (&)[_Size]' from 'int *' 

是否有可能使begin()end()意識到這一點?

+2

怎麼可能做_what_?你想達到什麼目的?你的目標是什麼? –

+2

改爲使用'std :: array',它具有C數組的所有功能,但實際上具有STL接口。它的迭代器被實現爲指針。 – rlbond

+0

@rlbond除了在這種情況下,普通數組是完全正確的。 – juanchopanza

回答

4

不,它是不可能對一個指針使用std::beginstd::end。與其大小是類型的一部分的數組不同,指針不能保持它指向的東西的大小。在你的情況有一個指針,你將不得不使用

std::find(pStart, pStart + SIZE, 5); 

的方式,以避免這雖然是使用std::vector時,你不會知道szie在編譯的時候什麼。它將爲您管理內存,並提供beginend成員函數。

+0

使用'std :: vector'查找涉及數據的副本。使用'std :: find(pStart,pStart + SIZE,5);'在這種情況下很好。 –

+0

@Stefano我在說,如果你使用的是運行時間大小,你應該使用'std :: vector'來啓動。如果沒有,那麼你可以使用一個原始數組,或者你可以使用'std :: array'。 – NathanOliver

+0

我正在使用C++數組,因爲數據來自共享內存,並且數組的大小由一種共享內存管理器動態分配。 –

2

這裏:

std::begin(pStart), std::end(pStart) 

你想採取一個指針的開始和結束。不!

相反,你的意思是:

std::begin(vect), std::end(vect) 

這是一樣的你是否使用數組或std::array,或std::vector,或者一個特別大的大象—得到一個容器的邊界,你需要集裝箱。

4

是否有可能使begin()和end()知道它?

這是可以實現的std::begin的指針,但它是不可能實現std::end(因爲就像你說的,大小是未知的),所以這是一個有點無意義

不過,你不需要或者那些使用std::find

int* p = std::find(pStart, pStart + SIZE, 5); 
+1

除了現在你有一個潛在的錯誤。像這樣的手動界限幾乎總是一個壞主意。 –

0

我想在C++數組中使用迭代器,但也使用原始指針。

你明白了。原始指針迭代器。它們遍歷數組。

您可以將它們用於您通過std::beginstd::end完成的所有事情。最值得注意的是,您可以將它們傳遞給<algorithm>中的C++標準算法。

指針本身不能迭代。迭代器不能迭代。

int* pStart = vect; 
std::find(std::begin(pStart), std::end(pStart), 5); 

非常嚴格意義上的指針只是一個數字。什麼是數字的「開始」和「結束」?這段代碼做一樣沒有意義如下:

int i = 123; 
std::find(std::begin(i), std::end(i), 5); // error 

是否有可能使begin()end()意識到這一點?

指針可能指向某個數組的開始。但是這些知識必須與指針一起保存。您需要保留一個大小或一個結束指針以及一個開始指針,並將所有數據保存在一起。

這正是std::arraystd::vector爲您所做的。

0

當我處理陣列我靠簡單的容器,以使它們與C++的的範圍一般治療兼容。

例如:

#include <iostream> 
#include <memory> // for std::unique_ptr 
#include <algorithm> // for std::reverse 
#include <numeric> // for std::iota 

template<typename T> 

class range_view { 

public: 

    range_view(T* data, std::size_t size) 
     : m_data { data }, 
     m_size { size } { } 

    const T* begin() const { return m_data; } 
    const T* end() const { return m_data + m_size; } 

    T* begin() { return m_data; } 
    T* end() { return m_data + m_size; } 

private: 

    T* m_data; 
    std::size_t m_size; 
}; 

int main() { 

    // this is your actual data 
    auto pdata = std::make_unique<int>(20); 

    // this is a handle you use to work with your data 
    auto data_view = range_view<int>(pdata.get(), 20); 

    // for example, you can fill it with numbers 0, ... , N - 1 
    std::iota(data_view.begin(), data_view.end(), 0); 

    // it is now compatible with c++'s range-based operators 
    std::cout << "my data...\n"; 
    for(auto && item : data_view) std::cout << item << " "; 

    std::reverse(data_view.begin(), data_view.end()); 
    std::cout << "\nreversed...\n"; 
    for(auto && item : data_view) std::cout << item << " "; 
    std::cout << "\n"; 
} 

編譯並運行

$ g++ example.cpp -std=c++14 
$ ./a.out 
my data... 
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 
reversed... 
19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 

你還是擔心傳遞正確尺寸的構造函數,如果底層指針被刪除,它就會失敗,但無論如何你必須擔心。