Khởi tạo mặc định của std :: array?


103

Với C ++ 11 std::array, tôi có đảm bảo rằng cú pháp std::array<T, N> x;sẽ khởi tạo mặc định tất cả các phần tử của mảng không?

CHỈNH SỬA : nếu không, có cú pháp nào sẽ hoạt động trên tất cả các mảng (bao gồm cả các mảng có kích thước bằng không) để khởi tạo tất cả các phần tử thành giá trị mặc định của chúng không?

CHỈNH SỬA : trên cppreference , mô tả hàm tạo mặc định cho biết:

(constructor) (implicitly declared) (public member function)
default-constructs or copy-constructs every element of the array 

vì vậy câu trả lời có thể là có. Nhưng tôi muốn chắc chắn điều đó theo tiêu chuẩn hoặc tiêu chuẩn tương lai.


Đừng nghĩ vậy. Nó được khai báo mặc định nên về cơ bản nó tương đương với T x[N]cú pháp.
Rapptz

Câu trả lời:


148

Theo định nghĩa, khởi tạo mặc định là khởi tạo xảy ra khi không có khởi tạo nào khác được chỉ định; ngôn ngữ C ++ đảm bảo với bạn rằng bất kỳ đối tượng nào mà bạn không cung cấp trình khởi tạo rõ ràng sẽ được khởi tạo mặc định (C ++ 11 §8.5 / 11). Điều đó bao gồm các đối tượng thuộc loại std::array<T, N>T[N].

Lưu ý rằng có những kiểu mà khởi tạo mặc định không có tác dụng và để lại giá trị của đối tượng là không xác định: bất kỳ kiểu không phải lớp, không phải mảng nào (§8.5 / 6). Do đó, một mảng đối tượng được khởi tạo mặc định với các kiểu như vậy sẽ có giá trị không xác định, ví dụ:

int plain_int;
int c_style_array[13];
std::array<int, 13> cxx_style_array;

Cả mảng kiểu c và std::arrayđược lấp đầy bởi các số nguyên có giá trị không xác định, cũng như plain_intcó giá trị không xác định.

Có cú pháp nào sẽ hoạt động trên tất cả các mảng (bao gồm cả các mảng có kích thước bằng 0) để khởi tạo tất cả các phần tử về giá trị mặc định của chúng không?

Tôi đoán rằng khi bạn nói "với giá trị mặc định của chúng", bạn thực sự có nghĩa là "khởi tạo tất cả các phần tử thành T{}". Đó không phải là khởi tạo mặc định , mà là khởi tạo giá trị (8,5 / 7). Bạn có thể yêu cầu khởi tạo giá trị khá dễ dàng trong C ++ 11 bằng cách cung cấp cho mỗi khai báo một bộ khởi tạo trống:

int plain_int{};
int c_style_array[13]{};
std::array<int, 13> cxx_style_array{};

Điều này sẽ khởi tạo giá trị lần lượt tất cả các phần tử của mảng, dẫn đến plain_old_intvà tất cả các thành viên của cả hai loại mảng đều được khởi tạo bằng 0.


Còn nếu đó là một thành viên của lớp: struct X {std :: array <int, 12> tens; X (): tens () {} Tôi có mười hai số không?
gerardw

4
@gerardw Theo tiêu chuẩn, có nó. Hãy coi chừng lỗi trong MSVC, nó không thể triển khai một số trường hợp khởi tạo giá trị một cách chính xác.
Casey

1
thực sự boost đã nói như vậy và giải quyết nó bằng boost::value_initialized liên kết của họ nhưng tôi tin rằng VC12 (VS2013) hiện đã được hỗ trợ tốt hơn nhiều.
v.oddou

1
Khiến tôi ước người mua thay đổi tiêu chuẩn thành giá trị khởi tạo mặc định và giá trị xác định theo yêu cầu. Tức là std :: array <int, 12> = {std :: undetined}; hoặc cái gì đó
Viktor Sehr

Trong thực tế, việc khởi tạo thứ gì đó thành một giá trị không xác định có nghĩa là gì? Giải pháp thay thế là gì?
Andrew

21

Khởi tạo mặc định là một thuật ngữ trong Tiêu chuẩn có thể có nghĩa là không có khởi tạo nào cả, vì vậy có thể ý bạn là không khởi tạo .

Mô tả tại cppreference.com thực sự có một chút sai lệch. std::arraylà một lớp tổng hợp và nếu kiểu phần tử là nguyên thủy, thì nó là POD: "dữ liệu cũ thuần túy", với ngữ nghĩa khớp chặt chẽ với ngôn ngữ C. Hàm tạo được xác định ngầm của std::array< int, N >là một hàm nhỏ hoàn toàn không làm gì cả.

Cú pháp như std::array< int, 3 >()hoặc cú pháp std::array< int, 3 > x{}cung cấp các giá trị bằng 0 không làm như vậy bằng cách gọi một phương thức khởi tạo. Nhận số 0 là một phần của khởi tạo giá trị , được chỉ định trong C ++ 11 §8.5 / 8:

Để khởi tạo giá trị một đối tượng kiểu T có nghĩa là:

- nếu T là loại lớp (có thể đủ điều kiện cv) không có hàm tạo mặc định do người dùng cung cấp hoặc bị xóa, thì đối tượng được khởi tạo bằng 0… và nếu T có hàm tạo mặc định không tầm thường, đối tượng được khởi tạo mặc định;

std::arraykhông có hàm tạo mặc định do người dùng cung cấp, vì vậy nó không được khởi tạo. Nó có một phương thức khởi tạo mặc định được xác định rõ ràng, nhưng nó rất nhỏ, vì vậy nó không bao giờ được khởi tạo mặc định. (Nhưng điều này không tạo ra sự khác biệt vì việc khởi tạo tầm thường theo định nghĩa không có tác dụng trong thời gian chạy.)

nếu không, có cú pháp nào sẽ hoạt động trên tất cả các mảng (bao gồm cả các mảng có kích thước bằng không) để khởi tạo tất cả các phần tử về giá trị mặc định của chúng không?

Mảng kiểu C và std::arraycả hai đều là tổng hợp và cách để khởi tạo hoàn toàn không cho bất kỳ tổng hợp nào là bằng cú pháp = {}. Điều này hoạt động kể từ C ++ 98. Lưu ý rằng mảng kiểu C không thể có phạm vi bằng không và điều đó sizeof (std::array< X, 0 >)không phải là số không.


6

Cả hai T x[N];std::array<T, N> x;mặc định-khởi tạo mọi phần tử của mảng.

Ví dụ, nếu T = std::string, mọi phần tử sẽ là một chuỗi rỗng. Nếu Tlà một lớp không có hàm tạo mặc định, cả hai sẽ không biên dịch được. Nếu T = int, mọi phần tử sẽ có giá trị không xác định (trừ khi khai báo đó xảy ra ở phạm vi không gian tên)


0

Trước hết, T x [N] không khởi tạo mặc định các phần tử, mặc dù việc khởi tạo mặc định kiểu vô hướng T thực sự không làm gì cả. Ở trên cũng áp dụng cho std :: array x. Tôi nghĩ những gì bạn cần là khởi tạo danh sách.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.