2017-02-06 16 views
7
#include <vector> 
struct S { int x; }; 
std::vector<S> v; 
int main() { v.resize(1000); return v[42].x; } 

Chương trình trên có được đảm bảo trả về 0 trong C++ 14 không? Tại sao?Vùng chứa cấu trúc chứa kiểu nguyên thủy, không được khởi tạo?

+0

Bản sao có thể có của [Khởi tạo tất cả tăng gấp đôi trong một lớp thành 0] (http://stackoverflow.com/questions/42010793/initializing-all-doubles-in-a-class-to-zero) – SU3

Trả lời

3

Vâng, bởi vì std::vector::resize và phương pháp tương tự thực hiện giá trị khởi tạo theo mặc định do đó giá trị khởi tạo các thành viên của uẩn:

Từ cppr:

Ảnh hưởng của giá trị khởi tạo là:
[...]
nếu T là loại lớp với hàm tạo mặc định không phải do người dùng cung cấp hoặc cũng không bị xóa (có nghĩa là, nó có thể là một lớp có định nghĩa ngầm hoặc mặc định d constructor mặc định), đối tượng là zero-initialized và sau đó nó là default-initialized nếu nó có một non-trivial default constructor;

Zero Initialiation phần làm những gì chúng ta cần:

Nếu T là một kiểu lớp phi công đoàn, tất cả các lớp cơ sở và các thành viên dữ liệu tĩnh không được zero-khởi tạo, và tất cả đệm được khởi tạo không bit. Các nhà thầu, nếu có, được bỏ qua.

Và tất nhiên, không khởi tạo của thành viên của chúng tôi làm điều đúng đắn:

Nếu T là một kiểu vô hướng, giá trị ban đầu của đối tượng là zero hằng số tích phân chuyển đổi một cách rõ ràng để T.


Công cụ phân bổ mặc định có thể sử dụng cách khởi tạo khác nhau. Bạn có thể sử dụng các giá trị đó để rời khỏi các giá trị như vậy được đơn lẻ hóa, xem toàn bộ bài viết trên default-insert.

3

Chương trình trên có được đảm bảo trả về 0 trong C++ 14 không? Tại sao?

Có. Từ [vector.capacity]:

void resize(size_type sz);
13 Hiệu ứng: Nếu sz < size(), xóa các size() - sz yếu tố cuối cùng từ chuỗi. Nếu không, hãy thêm sz - size()các phần tử được chèn vào mặc định vào chuỗi.

đâu, từ [container.requirements.general]:

Một yếu tố Xmặc định chèn nếu nó được khởi tạo bởi đánh giá của biểu thức allocator_traits<A>::construct(m, p) nơi p là địa chỉ của bộ nhớ chưa được khởi tạo cho phần tử được phân bổ trong phạm vi X.

construct cho std::allocator<T> có, từ [default.allocator]:

template <class U, class... Args> 
void construct(U* p, Args&&... args); 

Hiệu ứng: ::new((void *)p) U(std::forward<Args>(args)...)

Vì vậy, đó là giá trị khởi tạo. Chúng tôi đang thực hiện new S(), không phải new S, vì vậy, thành viên x sẽ không được khởi tạo.


Các cách tránh hành vi này (nếu muốn) là một trong hai:

  1. Thay đổi bộ cấp phát. Cung cấp loại cấp phát của riêng bạn có hai lần quá tải cho construct: một ô trống (sẽ được khởi tạo mặc định) và một lần lấy Args&&....
  2. Thay đổi loại. Thêm một hàm tạo mặc định vào S không khởi tạo.
Các vấn đề liên quan