2017-08-28 14 views
6

Tôi gần đây đã làm việc trên một dự án C + + và đã đi qua một trường hợp cạnh với các nhà xây dựng chuỗi mà tôi không thể hiểu đầy đủ. Các mã có liên quan (trong đó you can run here) như sau:Tại sao mã này để khởi tạo một chuỗi ký tự đơn lẻ gọi hàm khởi tạo initializer_list?

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

int main() { 
    string directParens(1, '*'); 
    string directBraces{1, '*'}; 
    string indirectBraces = {1, '*'}; 

    cout << directParens.size() << endl; // 1 
    cout << directBraces.size() << endl; // 2 
    cout << indirectBraces.size() << endl; // 2 
    return 0; 
} 

Các phiên bản cú đúp-khởi tạo của chuỗi kết thúc có hai nhân vật trong đó, cụ thể là, một char với giá trị số 1 theo sau là một ngôi sao.

Tôi không hiểu tại sao các phiên bản được khởi tạo bằng dấu ngoặc đơn của chuỗi gọi hàm dựng initializer_list thay vì hàm tạo có kích thước và ký tự. Các nhà xây dựng initializer_list có chữ ký này:

basic_string(std::initializer_list<CharT> init, 
      const Allocator& alloc = Allocator()); 

Cho rằng string là một bí danh cho basic_string char, chữ ký cụ thể sẽ là

string(std::initializer_list<char> init, 
     const Allocator& alloc = Allocator()); 

Làm thế nào là initializer {1, '*'}, trong đó có yếu tố cả hai loại int và loại char, phù hợp với nhà xây dựng này? Tôi đã ấn tượng rằng tất cả các chữ trong một std::initializer_list phải có cùng loại - đó có phải là không đúng?

+1

Lưu ý, có một ngoại lệ cho thu hẹp chuyển đổi [cho biểu thức không đổi có kết quả sau khi chuyển đổi sẽ phù hợp với loại mục tiêu] (https://stackoverflow.com/a/26974911/1708801) –

Trả lời

15

Trình khởi tạo {1, '*'}, chứa các phần tử kiểu int và kiểu char, khớp với hàm tạo này như thế nào?

Bởi vì cả hai nghĩa đen 1 và nhân vật '*' là mui trần để char mà không sử dụng một chuyển đổi thu hẹp. Do đó, họ đủ điều kiện để gọi cho nhà xây dựng initializer_list<char>. Và initializer_list nhà thầu luôn luôn được ưu tiên khi sử dụng khởi tạo danh sách. Nếu có thể gọi hàm tạo initializer_list từ các tham số, thì nó sẽ xảy ra.

Không bao giờ sử dụng dấu ngoặc đơn-init-danh sách với vùng chứa trừ khi bạn có ý định các thành phần trong danh sách là yếu tố của vùng chứa. Nếu bạn dự định chúng là các tham số hàm tạo, thì hãy sử dụng một hàm tạo.

+0

Ah, gotcha. Vì vậy, một bộ khởi tạo dấu ngoặc kép sẽ được hiểu là một initializer_list nếu tất cả các phần tử có thể được chuyển đổi thành kiểu cơ bản mà không thu hẹp chuyển đổi. Để xác nhận, điều đó có nghĩa là {3, 3.0} có thể được hiểu là initializer_list , nhưng không phải là initializer_list ? Và {INT_MAX, '*'} có thể là initializer_list ? – templatetypedef

+0

@templatetypedef: Vâng, ví dụ '{INT_MAX, '*'}' không thể * là 'initializer_list ', vì 'INT_MAX' không thể được chuyển thành' char' mà không có chuyển đổi thu hẹp. Nhưng nếu không, bạn đã đúng. –

+0

Ồ, tôi nghĩ rằng chuyển đổi thu hẹp được áp dụng cho * loại *, không phải là giá trị *. * Điều đó xóa mọi thứ! Cảm ơn! – templatetypedef

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