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

Une API que j'utilise fournit un résultat en tant que pointeur double*. Je veux envelopper avec le type std::vector<double>.C++ - tableau de pointeurs vers Vector?

+1

Rappelez-vous que vous pouvez obtenir 'std :: vECTOR' pour copier les éléments retournés de la array comme indiqué ci-dessous, mais si cette API s'attend à ce que vous appeliez une autre fonction pour libérer de la mémoire allouée au tableau, ou si vous supprimez le tableau vous-même, vous devez le faire. Créer le vecteur ne libèrera pas cette mémoire. – Praetorian

+0

Est-ce que votre fonction API * renvoie * un 'double *', ou prend-il un pointeur comme * argument * et le remplit avec des données? –

+0

Kerrek SB // bon point! quelque chose renvoie un double * quelque chose prend un pointeur comme argument. – webnoon

Répondre

23

Vous ne pouvez pas envelopper un tableau dans un vecteur à l'emplacement et attendez que le vecteur fonctionne sur ce groupe. Le mieux que vous pouvez faire est de donner le vecteur le double* et le nombre de valeurs, qui aura le vecteur faire une copie de chaque élément et de le mettre en lui-même:

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] 

Et aussi, comme l'a dit prétorienne, si le API que vous utilisez vous attend pour libérer de la mémoire après l'avoir utilisé, vous pourriez être intéressé par des pointeurs intelligents. Voir Praetorian's answer.

+3

Question simple avec peut-être une réponse complexe: POURQUOI est-il impossible d'envelopper un vecteur STL autour d'un existant tableau simple (en place)? Est-ce parce que STL suppose que la taille réservée est une puissance de 2? Sinon, je ne vois pas de raison pour le moment pourquoi cela ne devrait pas être possible ... –

+2

@JakobS. car le vecteur insiste sur le contrôle de l'allocation et de la réallocation de sa mémoire.Les garanties fournies par les fonctions membres ne pouvaient pas être conservées si le vecteur ne pouvait pas contrôler le tableau sous-jacent. –

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

Cela copiera les données values à un std::vector.

+1

'values' est un' double * ', pas un 'double []', donc 'sizeof (values) == sizeof (double *)', pas le nombre d'éléments dans le tableau. Vous avez besoin de 'std :: vector vec_values ​​(valeurs, valeurs + numValues)' – Praetorian

+0

@Praetorian: Désolé, j'ai oublié de faire ce changement – Jacob

1

Utilisez vecteur constructeur iterator

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

5

Les autres réponses montrent comment faire une copie du tableau retourné et créer un vector, mais en supposant que l'API alloue de la mémoire pour le réseau et attend à ce que l'appelant à supprimer Si vous le souhaitez, vous pouvez également envisager de placer le tableau dans un pointeur intelligent et de l'utiliser tel quel.

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

Vous pouvez toujours copier cela dans un vector mais si vous faites les étapes ci-dessus vous n'avez pas à vous soucier de la suppression du tableau retourné.

6

C'est probablement la réponse que vous cherchez. D'autres ont suggéré que vous ne pouvez pas envelopper un tableau dans un vecteur, mais ce n'est tout simplement pas vrai; Pensez-y, un vecteur a un tableau car c'est le conteneur de données sous-jacent! J'essayais ça depuis un certain temps avant de trouver une solution viable. L'inconvénient est que vous devez mettre à zéro les pointeurs après utilisation afin d'éviter de libérer la mémoire.

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

Sinon, vous pourriez juste faire une classe qui hérite de vecteur et les pointeurs nuls sur la destruction:

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