2010-10-15 20 views

Répondre

4

Si vous voulez que le vecteur soit visible dans la portée externe, vous devez le déclarer dans la portée externe. Ce qui signifie que vous devez également l'initialiser là. La seule façon de le déclarer sans initialisation est à l'aide d'un pointeur:

int main() 
{ 
    vector<string> * names = 0; 

    { 
    string s[] = {"Ben", "Joe", "Bob", "Matt"}; 
    names = new vector<string>(s, s+4); 
    } 

    // ... 
    delete names; 
} 
+0

Votre utilisation de pointeurs m'a donné une bonne idée. –

0

la mention de ldx de pointeurs m'a donné une idée. Je ne l'ai jamais utilisé shared_ptr avant, mais je pensais que ce pourrait être la solution, alors je les ai regardé, et je suis venu avec cette solution:

Edit: changé auto_ptr

int main() 
{ 
    auto_ptr<vector<string> > vsptr; 

    { 
     string s[] = {"Ben", "Joe", "Bob", "Matt"}; 
     int cnt = sizeof(s)/sizeof(string); 

     vsptr = auto_ptr<vector<string> >(new vector<string>(s,s+cnt)); 
    } 

    vector<string> &names = *vsptr; 
} 

I testé avec une classe qui annonce ses constructeurs, affectations et destructeurs, et il y a seulement une construction par défaut et une destruction. Bien sûr, cela nécessite un boost si votre compilateur n'implémente pas encore tr1, mais ce que vaut le compilateur n'en vaut pas la peine?

+1

std :: auto_ptr serait bien dans ce cas; vous ne partagez le pointeur nulle part. –

+0

Oui, vous avez raison. Il s'avère que je n'avais jamais utilisé auto_ptr non plus. –

+0

Une bonne idée en effet, mais vous devrez faire attention: Si vsptr sort de la portée avant que les noms le fassent, alors les noms deviendront invalides – ldx

0

Bien que pas initialisant strictement le vecteur, si vous voulez que votre objet soit auto plutôt que allouée dynamiquement vous pouvez échanger avec un temporaire:

{ 
    vector<string> names; 

    { 
     string s[] = {"Ben","Joe","Bob","Matt"}; 

     vector<string> init (s,s+4) 

     swap (names, init); 
    } 
} 

Bien que vous obtenez toujours les grandes copies en cours (l'omble chevalier * les littéraux copiés pour construire les chaînes std :: dans le tableau, puis les chaînes std :: dans le tableau copiées sur le vecteur) le swap évite la copie des chaînes depuis init vers les noms.

1
int main() 
{ 
    vector<string> names; 
    {  
     string s[] = {"Ben","Joe","Bob","Matt"}; 
     names.assign(s,s+4); 
    } 
} 
+0

Ici, le vecteur est initialisé dans la portée externe :) Cela pourrait ne pas être un problème à tout, mais ce n'est pas ce que la question a demandé. – gnud

+0

@gnud: Je le sais, mais je suppose que la question était plus pratique que théorique. Bien que je me trompe bien sûr –

0

Il n'y a aucun moyen de faire exactement ce que vous avez demandé. Il y a plusieurs possibilités, comme d'autres personnes l'ont fait remarquer:

  1. Déclarez le vecteur avant la portée interne et remplissez-le pendant. Cela a l'inconvénient que le vecteur traîne un peu vide, ce qui n'est pas un bon style, et il y a peut-être un débutant adolescent en l'initialisant plus tard plutôt que le constructeur, mais aucun d'entre eux ne devrait avoir beaucoup d'importance. doit être construit à un moment ou l'autre.

    // exemple de code d'insertion ici, chipé d'autre réponse (?)

  2. Déclarez une scoped_ptr (ou const auto_ptr ou pointeur normal) avant la portée intérieure et nouveau un vecteur dans le périmètre intérieur , en l'initialisant en utilisant le constructeur, et l'assigner au pointeur. Cela n'a presque aucun inconvénient. Vous devez vous habituer à utiliser -> plutôt que. mais la plupart des programmes C++ doivent le faire partout de toute façon. Il y a un petit risque que vous utilisiez accidentellement le pointeur non alloué avant la portée interne, mais il devrait immédiatement produire une exception, vous devriez donc le remarquer.

    // exemple de code d'insertion ici, chipé d'autres réponses (?)

  3. Enveloppez-vous soit toute la portée intérieure, ou tout simplement le tableau de chaînes, dans une fonction. Cela ressemble à de la complexité, mais honnêtement, j'ai très rarement regretté d'avoir l'initialisation constante dans une fonction clairement nommée.La fonction peut soit renvoyer le tableau, soit renvoyer un vecteur directement (selon que vous avez vraiment besoin de ces données dans la portée interne, ou que vous voulez simplement éviter de contaminer la portée externe). Selon votre chemin, il peut ressembler à quelque chose comme:

    vecteur MyFriends() { const chaîne s [] = {"Ben", "Joe", "Bob", "Matt"}; vecteur de retour (s, s + (sizeof (s)/sizeof (s [0]))); // TODO: améliore le calcul // Notez l'utilisation de l'optimisation de la valeur de retour // Cela n'a probablement pas d'importance, mais si vous y tenez, les compilateurs peuvent omettre un ou les deux // des objets vectoriels temporaires implicites. }

    int main() {{ // Faire des trucs // Si MyFriends dépend de choses, peut-être passer des choses dans cette func si possible // Si des choses juste besoin l'accès à MyFriends retour valeur, appelez ici encore } vecteur vec (MYFriends());

    // Plus de choses }

  4. Si vous voulez seulement initialiser le vecteur comme dans l'exemple 3, je pense que C++ 0x une syntaxe spécifique pour ce faire (??)

    // Fournir exemple

+0

Depuis que j'ai posé cette question, j'ai appris une bien meilleure façon de le faire, semblable à votre troisième exemple. Voir ma deuxième réponse. –

0

Depuis que je pose cette question, j'ai trouvé une bien meilleure façon de le faire en utilisant lambdas:

int main() 
{ 
    std::vector<std::string> v = []() -> std::vector<std::string> { 
     std::string s[] = {"Ben","Joe","Bob","Matt"}; 
     int cnt = sizeof(s)/sizeof(s[0]); 
     return std::vector<string>(s,s+cnt); 
    }(); 
}