27 votes

Que renvoie vec.data () si vec.size () == 0?

cppreference a cette note pour std::vector::data:

Retourne le pointeur vers le sous-jacent de la matrice de servir comme élément de stockage. Le pointeur est tel que la gamme [data(); data() + size()) est toujours une plage valide, même si le récipient est vide.

Que signifie "plage valide" signifie ici exactement? Ce sera data() de rendement si le vecteur est de longueur nulle?

Plus précisément, pour un zéro-longueur du vecteur:

  1. Peut - data() jamais être un pointeur null?
  2. Il peut être en toute sécurité déréférencé? (Même si c'points de junk.)
  3. Est-il garanti d'être différente entre les deux (de longueur nulle) les vecteurs?

Je travaille avec une bibliothèque C qui prend des tableaux et ne permettra pas un pointeur null, même pour un zéro-longueur du tableau. Cependant, il ne fait pas de déréférencement de la matrice de stockage pointeur si la longueur du tableau est égale à zéro, il vérifie juste si il est NULL. Je veux m'assurer que je peux passer data() de cette bibliothèque C, de sorte que la seule question pertinente est celle de (1) ci-dessus. (2) et (3) sont juste de la curiosité dans le cas où une situation similaire se présente.


Mise à jour

Sur la base des observations qui n'ont pas été tourné dans les réponses, on peut essayer le programme suivant:

#include <iostream>
#include <vector>

using namespace std;

int main() {
    vector<int> v;
    cout << v.data() << endl;

    v.push_back(1);
    cout << v.data() << endl;

    v.pop_back();
    cout << v.data() << endl;

    v.shrink_to_fit();
    cout << v.data() << endl;

    return 0;
}

Avec mon compilateur de sortie:

0x0
0x7f896b403300
0x7f896b403300
0x0

Ceci montre que:

  • data() peut en effet être un pointeur null, donc les réponses sont (1) oui (2) non (3) non

  • mais il n'est pas toujours un pointeur null pour un zéro-taille du vecteur

Oui, évidemment, j'aurais essayé avant de demander.

21voto

Matt McNabb Points 14273

"plage valide" est défini par [itérateur.les exigences.général]/7 (C++14):

"Range [i,j) est valide si et seulement si j est accessible à partir d' i".

Heureusement, C++ définit que l'ajout d' 0 d'un pointeur null renvoie un pointeur null. Donc, est un pointeur null accessible à partir d'un pointeur null ? Il est défini par le point 6 de la même section:

Un itérateur j est appelé accessible à partir d'un itérateur i si et seulement si il existe une suite finie d'applications de l'expression ++i qui fait i == j.

Un zéro-longueur de la séquence est une suite finie, donc data() peut retourner un pointeur null.

En conséquence, les réponses à vos questions sont les suivantes:

  1. Peut - data() jamais être un pointeur null?

Oui

  1. Il peut être en toute sécurité déréférencé? (Même si c'points de junk.)

Pas de

  1. Est-il garanti d'être différente entre les deux (de longueur nulle) les vecteurs?

Pas de

5voto

Captain Giraffe Points 5907

Trop long pour un commentaire alors postez ici.

Je m'attendais à ce que les itérateurs soient nullptr pour une séquence vide, alors je l'ai testée.

 #include <iostream>
#include <vector>

void pr(std::vector<int>& v){
    std::cout << &*v.begin() << ", " << &*v.end() << "\n";
} 
// technically UB, but for this experiment I don't feel too bad about it.
// Thanks @Revolver    
int main(int argc, char** argv) {
    std::vector<int> v1;
    std::vector<int> v2;

    pr(v1);
    pr(v2);

    return 0;
}
 

Et cela imprime en effet

 0, 0
0, 0 
 

Maintenant, pour un conteneur vide, la seule opération raisonnable pour une plage valide est begin() == end() . Et non, les fichiers indésirables ne peuvent pas être déréférencés, donc * v.begin () n'est pas un problème.

5voto

Paul Evans Points 8997

De la norme:

23.3.6.4 [vector.data]

T * data () noexcept;

const T * data () const noexcept;

Renvoie: un pointeur tel que [data (), data () + size ()) est une plage valide . Pour un vecteur non vide, data () == & front ().

Il est donc permis d'être nul pour un vecteur vide mais pas nécessairement déréférençable ni unique.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X