30

Tôi hỏi một câu hỏi ở đây: Lifetime Extension of a initializer_list return liên quan đến mã không có chức năng:Danh sách kèm theo xoăn-Brace Nếu không phải là một intializer_list?

const auto foo = [](const auto& a, const auto& b, const auto& c) { return {a, b, c}; }; 

Tôi tin rằng lambda đã cố gắng để trả lại một intializer_list (đó là xấu, không làm điều đó.) Nhưng tôi có một comment:

It's not an initializer_list , it's an initializer list. Two different things.

Tôi chỉ nghĩ rằng bất cứ khi nào bạn tạo danh sách có dấu ngoặc nhọn bạn đang tạo intializer_list. Nếu đó không phải là những gì đang xảy ra, một danh sách trong ngoặc nhọn là gì?

+0

Chỉ là: error: return initializer list. –

+1

@ DieterLücking Bạn phải có lỗi của bạn được bật lên cao hơn tôi. Tôi thậm chí không nhận được một cảnh báo lần đầu tiên tôi đã cố gắng này, mặc dù như đã nêu trong câu hỏi liên kết này là * không * mã tốt. –

+0

@JonathanMee Dưới đây SO câu hỏi cũng có một số câu trả lời hữu ích để biết: http://stackoverflow.com/questions/29200036/is-providing-a-private-constructor-for-initializer-list-conforming – Arunmu

Trả lời

10

Có ba khác biệt, nhưng khái niệm liên quan ở đây:

  1. chuẩn bị tinh thần-init-list: Các quy tắc ngữ pháp liên quan đến danh sách xoăn-cú đúp kín trong những bối cảnh nhất định.

  2. danh sách Initializer: Các tên cho chuẩn bị tinh thần-init-list initializer sử dụng trong list-khởi.

  3. std::initializer_list: Lớp bao gồm một mảng tạm thời được tạo trong một số ngữ cảnh liên quan đến braced-init-list s.

Một số ví dụ:

//a braced-init-list and initializer list, 
//but doesn't create a std::initializer_list 
int a {4}; 

//a braced-init-list and initializer list, 
//creates a std::initializer_list 
std::vector b {1, 2, 3}; 

//a braced-init-list and initializer list, 
//does not create a std::initializer_list (aggregate initialization) 
int c[] = {1, 2, 3}; 

//d is a std::initializer_list created from an initializer list 
std::initializer_list d {1, 2, 3}; 

//e is std::initializer_list<int> 
auto e = { 4 }; 

//f used to be a std::initializer_list<int>, but is now int after N3922 
auto f { 4 }; 

Bạn có thể muốn đọc N3922, mà thay đổi một số quy định liên quan đến autostd::initializer_list.

28

Đây là số braced-init-list. A braced-init-list tồn tại trước std::initializer_list và được sử dụng để initialize aggregates.

int arr[] = {1,2,3,4,5}; 

Trên đây sử dụng một chuẩn bị tinh thần-init-list để khởi tạo mảng, không std::initializer_list được tạo ra. Mặt khác khi bạn làm

std::vector<int> foo = {1,2,3,4,5}; 

foo không phải là một tổng hợp nên chuẩn bị tinh thần -init-list được sử dụng để tạo ra một std::initializer_list mà là ở quay truyền cho constructor của foo chấp nhận một std::initializer_list.

Một điều cần lưu ý về một braced-init-list là không có loại để quy tắc đặc biệt được phát triển để sử dụng với nó và auto. Nó có các hành vi sau đây (kể từ khi áp dụng các N3922)

auto x1 = { 1, 2 }; // decltype(x1) is std::initializer_list<int> 
auto x2 = { 1, 2.0 }; // error: cannot deduce element type 
auto x3{ 1, 2 }; // error: not a single element 
auto x4 = { 3 }; // decltype(x4) is std::initializer_list<int> 
auto x5{ 3 }; // decltype(x5) is int 

Và bạn có thể tìm thêm thông tin về lịch sử của hành vi này và tại sao nó được đổi tại địa chỉ: Why does auto x{3} deduce an initializer_list?

+0

Vì vậy, nếu tôi làm, 'auto foo = {1, 2, 3, 4, 5}' loại 'foo' là gì? Nó được đảm bảo là một 'intializer_list'? –

+1

@JonathanMee Tôi nghĩ bản cập nhật sẽ bao gồm nội dung đó ngay bây giờ. – NathanOliver

+0

Tôi ước chúng tôi có một cái tên tốt hơn cho cái này so với nonterminal ... –

7

I just thought that any time you did a curly-braced list you were creating an intializer_list .

Đó không phải là chính xác.

If that's not what's happening, what is a list in curly-braces?

struct Foo {int a; int b;}; 
Foo f = {10, 20}; 

Phần {10, 20} không phải là một initializer_list. Nó chỉ là một dạng cú pháp để sử dụng một danh sách các đối tượng để tạo một đối tượng khác.

int a[] = {10, 20, 30}; 

Một lần nữa, đây là một dạng cú pháp để tạo mảng.

Tên cho mẫu cú pháp là braced-init-list.

+0

Vì vậy, cùng một câu hỏi tôi đã hỏi, @NathanOliver: "Nếu tôi làm,' auto foo = {1, 2, 3, 4, 5} 'loại' foo' là gì? Nó được đảm bảo là một 'intializer_list'? " –

+1

Đó sẽ là 'std :: initializer_list '. –

1

Bạn có hai điều khác nhau khi sử dụng {}

  1. A Loại std::initializer_list<T> nơi các giá trị có thể được ngầm chuyển đổi sang T
  2. Một loại có thể được khởi tạo với các giá trị của danh sách.

Loại đầu tiên buộc một danh sách đồng nhất và loại thứ hai không. Trong ví dụ tiếp theo:

struct S{ 
    int a; 
    string b 
}; 

void f1(S s); 
void f2(int i); 
void f3(std::initializer_list<int> l); 

f1({1, "zhen"}); // construct a temporal S 
f2({1});   // construct a temporal int 
f3({1,2,3});  // construct a temporal list of ints 

Các chức năng f1 và f2 sử dụng loại đầu tiên và f3 sử dụng loại thứ hai. Bạn nên biết rằng nếu có sự mơ hồ, std :: initializer_list được ưu tiên. Ví dụ:

void f(S s); 
void f(int i); 
void f(std::initializer_list<int> l); 

f({1, "zhen"}); // calls with struct S 
f({1});   // calls with int list with one element 
f({1,2,3});  // calls with int list with three elements 
Các vấn đề liên quan