#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?
#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?
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;
và 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.
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ếusz < size()
, xóa cácsize() - sz
yếu tố cuối cùng từ chuỗi. Nếu không, hãy thêmsz - 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ố
X
là mặc định chèn nếu nó được khởi tạo bởi đánh giá của biểu thứcallocator_traits<A>::construct(m, p)
nơip
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 viX
.
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:
construct
: một ô trống (sẽ được khởi tạo mặc định) và một lần lấy Args&&...
.S
không khởi tạo.
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