2011-09-02 407 views
19
double * values; // instead of this, 
std::vector<double> values; // I want this. 

我使用的API提供了一個結果作爲double*指針。我想用std::vector<double>類型來包裝它。C++ - 指向向量的指針數組?

+1

請記住,你可以得到'的std :: VECTOR'複製的元素從返回數組,如下所示,但如果此API期望您調用另一個函數來釋放爲該數組分配的內存,或者自己刪除該數組,則必須這樣做。創建矢量不會釋放該內存。 – Praetorian

+0

你的API函數*返回一個'double *',還是將指針作爲*參數*並用數據填充它? –

+0

Kerrek SB //好點!某些東西會返回一個double *東西需要一個指針作爲參數。 – webnoon

回答

23

你不能在一個向量的地方包裝一個數組,並期望向量在該數組上運行。你能做的最好的就是給向量double*和值的數量,這將有載體使每個元素的副本,並把它放在自己:

int arrlen = 0; 

// pretending my_api takes arrlen by reference and sets it to the length of the array 
double* dbl_ptr = my_api(arrlen); 

vector<double> values(dbl_ptr, dbl_ptr + arrlen); 

// note that values is *not* using the same memory as dbl_ptr 
// so although values[0] == dbl_ptr[0], &values[0] != &dbl_ptr[0] 

而且還像禁衛軍說,如果您使用的API期望您在使用後釋放內存,您可能對智能指針感興趣。見Praetorian's answer

+3

簡單的問題也許是一個複雜的答案:爲什麼沒有辦法將STL向量包裹在現有的普通數組(就地)?是否因爲STL假定保留大小是2的冪次?否則,我目前沒有看到一個理由,爲什麼這不應該是可能的... –

+2

@JakobS。因爲矢量堅持控制其內存的分配和重新分配。如果向量無法控制底層數組,則成員函數所做的保證不會成立。 –

4
const int N = 10; // Number of elements in your array 
std::vector<double> vec_values(values, values + N); 

這將在values將數據複製到一個std::vector

+1

'values'是一個double *',而不是'double []',所以'sizeof(values)== sizeof(double *)',而不是數組中元素的個數。你需要'std :: vector vec_values(values,values + numValues)' – Praetorian

+0

@Praetorian:對不起,忘了做這個改變 – Jacob

1

使用向量迭代器構造

std::vector<int> value_vec (value, value + n); //suppose value has n elements

5

其他的答案顯示如何使返回數組的副本,並創建一個vector,但假設該API爲數組分配內存,並希望呼叫者刪除它可能還需要考慮將數組粘貼到智能指針中並按原樣使用它。

int numValues; 
std::unique_ptr<double[]> values(apiFunction(&numValues)); 

,您仍然可以複製此爲vector,但如果你做上面的步驟,你不必擔心刪除返回的數組。

6

這可能是您正在尋找的答案。其他人建議你不能在一個向量中包裝一個數組,但這是不正確的;想想看,一個向量有一個數組,因爲它是底層的數據容器!在我想出一個可行的解決方案之前,我一直在試圖解決這個問題。需要注意的是,你必須在使用後清零指針,以避免雙重釋放內存。

#include <vector> 
#include <iostream> 

template <class T> 
void wrapArrayInVector(T *sourceArray, size_t arraySize, std::vector<T, std::allocator<T> > &targetVector) { 
    typename std::_Vector_base<T, std::allocator<T> >::_Vector_impl *vectorPtr = 
    (typename std::_Vector_base<T, std::allocator<T> >::_Vector_impl *)((void *) &targetVector); 
    vectorPtr->_M_start = sourceArray; 
    vectorPtr->_M_finish = vectorPtr->_M_end_of_storage = vectorPtr->_M_start + arraySize; 
} 

template <class T> 
void releaseVectorWrapper(std::vector<T, std::allocator<T> > &targetVector) { 
    typename std::_Vector_base<T, std::allocator<T> >::_Vector_impl *vectorPtr = 
     (typename std::_Vector_base<T, std::allocator<T> >::_Vector_impl *)((void *) &targetVector); 
    vectorPtr->_M_start = vectorPtr->_M_finish = vectorPtr->_M_end_of_storage = NULL; 
} 

int main() { 

    int tests[6] = { 1, 2, 3, 6, 5, 4 }; 
    std::vector<int> targetVector; 
    wrapArrayInVector(tests, 6, targetVector); 

    std::cout << std::hex << &tests[0] << ": " << std::dec 
      << tests[1] << " " << tests[3] << " " << tests[5] << std::endl; 

    std::cout << std::hex << &targetVector[0] << ": " << std::dec 
      << targetVector[1] << " " << targetVector[3] << " " << targetVector[5] << std::endl; 

    releaseVectorWrapper(targetVector); 
} 

或者,你可以只讓從向量和空出來的指針在破壞繼承的類:

template <class T> 
class vectorWrapper : public std::vector<T> 
{ 
public: 
    vectorWrapper() { 
    this->_M_impl _M_start = this->_M_impl _M_finish = this->_M_impl _M_end_of_storage = NULL; 
    } 

    vectorWrapper(T* sourceArray, int arraySize) 
    { 
    this->_M_impl _M_start = sourceArray; 
    this->_M_impl _M_finish = this->_M_impl _M_end_of_storage = sourceArray + arraySize; 
    } 

    ~vectorWrapper() { 
    this->_M_impl _M_start = this->_M_impl _M_finish = this->_M_impl _M_end_of_storage = NULL; 
    } 

    void wrapArray(T* sourceArray, int arraySize) 
    { 
    this->_M_impl _M_start = sourceArray; 
    this->_M_impl _M_finish = this->_M_impl _M_end_of_storage = sourceArray + arraySize; 
    } 
};