C++ - 指向Vector的指针数组?

web*_*oon 30 c++

double * values; // instead of this,
std::vector<double> values; // I want this.
Run Code Online (Sandbox Code Playgroud)

我正在使用的API提供结果作为double*指针.我想用这个std::vector<double>类型包装它.

Set*_*gie 30

您无法将数组包装在向量中,并期望向量在该数组上运行.你可以做的最好的事情是给出向量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]
Run Code Online (Sandbox Code Playgroud)

而且,正如Praetorian所说,如果你使用的API希望你在使用后释放内存,你可能会对智能指针感兴趣.请参阅Praetorian的回答.

  • @JakobS.因为向量坚持控制其内存的分配和重新分配.如果向量无法控制底层数组,则成员函数所做的保证无法成立. (4认同)
  • 简单的问题可能是一个复杂的答案:为什么没有办法在现有的普通数组(就地)周围包装STL向量?是因为STL假设保留大小是2的幂?否则我现在看不出为什么这不可能...... (3认同)

Eth*_*eal 11

其他人建议你不能将数组包装在一个向量中,但这根本不是真的; 想一想,矢量有一个数组作为它的底层数据容器!在我想出一个可行的解决方案之前,我已经尝试了很长时间.需要注意的是,您必须在使用后将指针归零,以避免双重释放内存.

#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 );
}
Run Code Online (Sandbox Code Playgroud)

或者,您可以创建一个继承自vector的类,并在销毁时将指针归零:

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;
  }   
};  
Run Code Online (Sandbox Code Playgroud)


Jac*_*cob 5

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

这会将数据复制values到a std::vector.


Pra*_*ian 5

其他答案显示如何制作返回数组的副本并创建一个vector,但假设API为数组分配内存并期望调用者删除它,您可能还需要考虑将数组插入智能指针并使用它原样.

int numValues;
std::unique_ptr<double[]> values( apiFunction( &numValues ) );
Run Code Online (Sandbox Code Playgroud)

您仍然可以将其复制到一个vector但是如果您执行上述步骤,则无需担心删除返回的数组.


Miz*_*zux 5

如果使用 C++11,您可以使用std::vector<std::reference_wrapper<double>>.

#include <functional> // std::reference_wrapper
#include <vector>

#include <iostream>
#include <numeric> // std::iota
#include <random> // std::mt19937
#include <algorithm> // std::shuffle

int main() {
const int N = 10; // Number of elements in your array
double values[N];
std::iota(values, values+N, -4.0);

std::vector<std::reference_wrapper<double>> v(values, values + N);
std::shuffle(v.begin(), v.end(), std::mt19937{std::random_device{}()});

std::cout << "Contents of the array: ";
for(auto i=0; i < N; ++i) std::cout << values[i] << ' ';
std::cout << '\n';

std::cout << "Contents of the array, shuffled: ";
for(auto i: v) std::cout << i << ' ';
std::cout << '\n';

std::cout << "Change values using the vector shuffled\n";
auto j = 44.;
for(double& i: v) i = ++j;

std::cout << "Contents of the array, shuffled: ";
for(auto i: v) std::cout << i << ' ';
std::cout << '\n';
    
std::cout << "Contents of the array: ";
for(auto i=0; i < N; ++i) std::cout << values[i] << ' ';
std::cout << '\n';
}
Run Code Online (Sandbox Code Playgroud)

可能的输出:

Contents of the array: -4 -3 -2 -1 0 1 2 3 4 5 
Contents of the array, shuffled: 1 3 -2 0 -3 5 -4 4 -1 2 
Change values using the vector shuffled
Contents of the array, shuffled: 45 46 47 48 49 50 51 52 53 54 
Contents of the array: 51 49 47 53 48 45 54 46 52 50
Run Code Online (Sandbox Code Playgroud)

优点:零拷贝

参考:https://en.cppreference.com/w/cpp/utility/function/reference_wrapper