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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7278347/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 16:43:38  来源:igfitidea点击:

C++ - pointer array to Vector?

c++

提问by webnoon

double * values; // instead of this,
std::vector<double> values; // I want this.

An API I'm using provides a result as double*pointer. I want to wrap this with the std::vector<double>type.

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

采纳答案by Seth Carnegie

You can't wrap an array in a vector in placeand expect the vector to operate on that array. The best you can do is give the vector the double*and the number of values, which will have the vector make a copy of every element and put it in itself:

您不能将数组包装在向量并期望向量对该数组进行操作。你能做的最好的事情是给向量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]

And also, like Praetorian said, if the API you are using expects you to free the memory after using it, you might be interested in smart pointers. See Praetorian's answer.

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

回答by Ethereal

Others have suggested that you cannot wrap an array in a vector, but that's simply not true; think about it, a vector has an array as it's underlying data container! I had been attempting this off and on for quite some time before I came up with a workable solution. The caveat is that you have got to zero out the pointers after use in order to avoid double-freeing the memory.

其他人建议您不能将数组包装在向量中,但事实并非如此;想想看,向量有一个数组,因为它是底层数据容器!在我想出一个可行的解决方案之前,我已经断断续续地尝试了很长一段时间。需要注意的是,您必须在使用后将指针清零,以避免双重释放内存。

#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 );
}

Alternatively you could just make a class that inherits from vector and nulls out the pointers upon destruction:

或者,您可以创建一个从 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;
  }   
};  

回答by Jacob

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

This will copy the data in valuesto a std::vector.

这会将数据复制valuesstd::vector.

回答by Praetorian

The other answers show how to make a copy of the returned array and create a vector, but assuming the API allocates memory for the array and expects the caller to delete it, you may also want to consider sticking the array into a smart pointer and using it as is.

其他答案显示了如何复制返回的数组并创建一个vector,但假设 API 为数组分配内存并期望调用者删除它,您可能还需要考虑将数组粘贴到智能指针中并使用它照原样。

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

You can still copy this into a vectorbut if you do the above steps you don't have to worry about deleting the returned array.

您仍然可以将其复制到 avector但如果您执行上述步骤,则不必担心删除返回的数组。

回答by ChanDon

Use vector iterator constructor

使用向量迭代器构造函数

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

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

回答by Hamid Reza Arzaghi

Thanks to @Ethereal for the nice solution and to make his/her answer more complete:

感谢@Ethereal 提供了很好的解决方案并使他/她的回答更加完整:

that code will not compile in visual c++ (maybe will in GCC) because of differences in the std implementation but with some changes, it will work perfectly.

由于 std 实现的差异,该代码不会在 Visual C++ 中编译(可能会在 GCC 中编译),但经过一些更改,它将完美运行。

this code tested in Microsoft Visual C++ (VS2015):

此代码在 Microsoft Visual C++ (VS2015) 中测试:

#include <iostream>
#include <vector>

template<typename T> std::vector<T> wrapArrayInVector(T* sourceArray, size_t arraySize) {
    std::vector<T> targetVector;
    std::vector<T>::_Mybase* basePtr{ (std::vector<T>::_Mybase*)((void*)&targetVector) };
    basePtr->_Get_data()._Myfirst = sourceArray;
    basePtr->_Get_data()._Mylast = basePtr->_Get_data()._Myend = basePtr->_Get_data()._Myfirst + arraySize;
    return targetVector;
}

int main() {
    int* tests{ new int[3] };
    tests[0] = 100; tests[1] = 200; tests[2] = 300;
    std::vector<int> targetVector{ wrapArrayInVector(tests, 3) };
    std::cout << std::hex << &tests[0] << ": " << std::dec
    << tests[0] << " " << tests[1] << " " << tests[2] << std::endl;
    std::cout << std::hex << &targetVector[0] << ": " << std::dec
    << targetVector[0] << " " << targetVector[1] << " " << targetVector[2] << std::endl;
    std::cin.get();
}

CAUTION:

警告:

but you should be noticed you can wrap an array pointer in std::vector just if that pointer is allocated in heap(for example using new keyword) because std::vector is trying to delete the pointer in its destructor, and if array pointer is allocated on the stack it will cause double delete same memory address and it will cause run time error.

但是你应该注意到你可以在 std::vector 中包装一个数组指针,只要该指针在堆中分配(例如使用 new 关键字),因为 std::vector 试图删除其析构函数中的指针,并且如果数组指针在堆栈上分配它会导致双重删除相同的内存地址,并会导致运行时错误。

so you must notwrap stack allocated array pointer like this

所以你不能像这样包装堆栈分配的数组指针

int tests[3];
tests[0] = 100; tests[1] = 200; tests[2] = 300;
std::vector<int> targetVector = wrapArrayInVector(tests, 3);