2016-02-04 17 views
13

Tôi biết rằng tôi có thể sử dụng mảng ký tự và cũng có danh sách khởi tạo để lấp đầy chuỗi.Chuỗi C++ - hành vi lạ khi sử dụng hàm tạo danh sách khởi tạo

Dường như trình biên dịch tạo ra một số quảng cáo ngầm từ int đến initializer_list hoặc cấp phát. Nhưng tôi không biết tại sao nó không cho tôi bất kỳ cảnh báo nào và tại sao nó lại làm cho nó ngầm.

Bạn có thể giải thích cho tôi điều gì xảy ra với chuỗi s4 và s5 không?

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

Bạn có thể giải thích cho tôi những gì bạn mong đợi thay vì điều gì sẽ xảy ra? Tôi không thể thấy bất cứ điều gì không chủ ý trong đoạn mã này. – dhein

+0

Vâng, tất nhiên. Tôi đã mong đợi các hành vi tương tự cho cả hai nhà xây dựng, một trong những lấy mảng của chars và initializer danh sách là tốt. – tomekpe

Trả lời

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

Trên thực tế, những người khởi tạo không chỉ cần gọi các nhà xây dựng std::initializer_list. Đối số thứ hai không thể được chuyển đổi hoàn toàn thành std::allocator, do đó các nhà thầu khác được xem xét. Các constructor được gọi là một với chữ ký này:

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

các nhà xây dựng std::initializer_list được sử dụng để tạo ra một tạm thời std::string từ chuẩn bị tinh thần-init-list để vượt qua như other lập luận để các nhà xây dựng ở trên. Tạm thời có thể liên kết với nó bởi vì nó là một tham chiếu đến const. Đối số thứ hai, do đó, là đối số pos, được sử dụng làm điểm bắt đầu của việc xây dựng bản sao chuỗi con.

Vì vậy s6 là các nhân vật trong khoảng [3, 5) (ví dụ: "45") và s7 là các nhân vật trong khoảng [5,5) (ví dụ: "").

+3

Wow. Những cạm bẫy là một ví dụ về những gì làm cho C++ khó có được, đôi khi. – kebs

+4

Tôi không hiểu những gì khác OP mong đợi ?! – dhein

+3

Họ hy vọng trình biên dịch sẽ phàn nàn rằng không có chuyển đổi ngầm từ '5' thành' const std :: allocator & 'bởi vì họ chỉ xem xét constructor đó là một tùy chọn. –

Các vấn đề liên quan