2011-09-02 338 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; 
    } 
};