Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ string - strange behaviour when using initialization list constructor

I know that I can use array of chars and also initialization list to fill a string.

It looks that the compiler makes some implicit promotion from int to initializer_list or allocator. But I don't know why it doesn't give me any warning and why it makes it implicit.

Could you explain to me what happens with strings s4, and 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;
}
like image 449
LookAheadAtYourTypes Avatar asked Feb 04 '16 12:02

LookAheadAtYourTypes


People also ask

Should my constructors use initialization lists or assignment?

Initialization lists. In fact, constructors should initialize as a rule all member objects in the initialization list.

What is initialization list in constructor?

Initializer List is used in initializing the data members of a class. The list of members to be initialized is indicated with constructor as a comma-separated list followed by a colon. Following is an example that uses the initializer list to initialize x and y of Point class.

Is initialization list faster?

Conclusion: All other things being equal, your code will run faster if you use initialization lists rather than assignment.

Do strings need to be initialized?

If you are talking about std::string , you don't need to "initialize" it because it is automatically initialized to the empty string in its constructor.


1 Answers

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

Actually, those initializations don't just call the std::initializer_list constructor. The second argument cannot be implicitly converted to std::allocator, so other constructors are considered. The constructor called is the one with this signature:

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

The std::initializer_list constructor is used to create a temporary std::string from the braced-init-list to pass as the other argument to the above constructor. The temporary can bind to that because it's a reference-to-const. The second argument, therefore, is the pos argument, which is used as the starting point of a substring copy construction.

So s6 is the characters in the interval [3, 5) (i.e. "45") and s7 is the characters in the interval [5,5) (i.e. "").

like image 164
TartanLlama Avatar answered Sep 21 '22 22:09

TartanLlama