Question Chaîne C ++ - comportement étrange lors de l'utilisation du constructeur de liste d'initialisation


Je sais que je peux utiliser un tableau de caractères et une liste d'initialisation pour remplir une chaîne.

Il semble que le compilateur fasse une promotion implicite de int vers initializer_list ou allocator. Mais je ne sais pas pourquoi cela ne me donne aucun avertissement et pourquoi cela le rend implicite.

Pourriez-vous m'expliquer ce qui se passe avec les cordes s4 et s5?

http://ideone.com/5Agc2T

#include <iostream>
#include <string>
using namespace std;

class A{
};

int main() {

    // string::string(charT const* s)
    string s1("12345");
    // 5 - because constructor takes into account null-terminated character
    cout << s1.size() << endl;      

    // string(std::initializer_list<charT> ilist)
    string s2({'1','2','3','4','5'});   
    // 5 - because string is built from the contents of the initializer list init.  
    cout << s2.size()<<endl;

    // string::string(charT const* s, size_type count)
    string s3("12345",3);
    // 3 -  Constructs the string with the first count characters of character string pointed to by s
    cout << s3.size() << endl;

    // basic_string( std::initializer_list<CharT> init,const Allocator& alloc = Allocator() ); - ?
    string s4({'1','2','3','4','5'},3);
    // 2 - why this compiles (with no warning) and what this result means?
    cout << s4.size() << endl;



    string s5({'1','2','3','4','5'},5);
    // 0 - why this compiles (with no warning) and what this result means?
    cout << s5.size() << endl;

    // basic_string( std::initializer_list<CharT> init,const Allocator& alloc = Allocator() );
    // doesn't compile, no known conversion for argument 2 from 'A' to 'const std::allocator<char>&'
    //string s6({'1','2','3','4','5'},A());
    //cout << s6.size() << endl;

    return 0;
}

13
2018-02-04 12:14


origine


Réponses:


string s6({'1','2','3','4','5'},3);
string s7({'1','2','3','4','5'},5);

En fait, ces initialisations n'appellent pas simplement la std::initializer_list constructeur. Le second argument ne peut pas être implicitement converti en std::allocator, donc d'autres constructeurs sont considérés. Le constructeur appelé est celui avec cette signature:

basic_string( const basic_string& other, 
              size_type pos, 
              size_type count = std::basic_string::npos,
              const Allocator& alloc = Allocator() );

le std::initializer_list constructeur est utilisé pour créer un temporaire std::string à partir de braced-init-list pour passer en tant que other argument au constructeur ci-dessus. Le temporaire peut se lier à cela car c'est une référence à const. Le deuxième argument est donc le pos argument utilisé comme point de départ d’une construction de copie de sous-chaîne.

Alors s6 est les caractères dans l'intervalle [3, 5) (c'est à dire. "45") et s7 est les caractères dans l'intervalle [5,5) (c'est à dire. "").


28
2018-02-04 12:23