2010-03-10 26 views
135

Trình tạo mặc định (được tạo bởi trình biên dịch) có khởi tạo các kiểu dựng sẵn không?Trình tạo mặc định có khởi tạo các kiểu dựng sẵn không?

+14

Ngạc nhiên đây là một CW - điều này không thực sự có một câu trả lời đúng, nó không phải là chủ quan, không phải là một chủ đề thảo luận . –

+0

Vâng, đó là một phán quyết kỳ lạ. Tại sao điều này được chuyển sang CW? –

+1

Vì OP là một người dùng mới, tôi đoán anh ấy đã phạm sai lầm. – Gorpik

Trả lời

1

Theo tiêu chuẩn, nó không trừ khi bạn rõ ràng khởi tạo trong danh sách initializer

+2

Vâng, bạn không thể chỉ định bất kỳ thứ gì trong hàm tạo mặc định * được tạo bởi trình biên dịch * – Gorpik

+2

@Gorpik - Điểm được lấy ... nhưng wen tôi nói rõ ràng là khởi tạo, ý tôi là phải cung cấp rõ ràng hàm tạo mặc định – mukeshkumar

+0

@hype: I biết, nhưng OP đã chỉ rõ rằng anh ta đang nói về constructor mặc định được tạo ra bởi máy tính, chứ không phải cái mà bạn cung cấp cho chính mình. – Gorpik

-6

số Các constructor mặc định cấp phát bộ nhớ và gọi constructor không tham số của bất kỳ bậc cha mẹ.

+5

Và nhà xây dựng no-arg của bất kỳ thành viên nào không thuộc POD. –

+0

Nhà xây dựng có cấp phát bộ nhớ hay bộ đệm "cấp phát" cho cá thể và sau đó gọi hàm tạo không? – visitor

+4

Câu trả lời này khá sai lầm ... 1/Constructor không cấp phát bộ nhớ nào, nó khởi tạo nó. 2/Câu hỏi là về xây dựng-in và câu trả lời này là về các lớp học phụ huynh ... làm thế nào đến sai câu trả lời off-topic này có 8 phiếu bầu? –

-3

Về mặt kỹ thuật, nó khởi tạo chúng - bằng cách sử dụng hàm tạo mặc định của chúng, điều này ngẫu nhiên không làm gì ngoài việc cấp phát bộ nhớ cho chúng.

Nếu những gì bạn muốn biết là liệu chúng có được đặt thành thứ gì đó lành mạnh như 0 cho int giây hay không, thì câu trả lời là "không".

+3

constrctor không cấp phát bộ nhớ.Constructor được thực hiện sau khi cấp phát bộ nhớ. Vui lòng sửa tôi nếu tôi sai. – ZoomIn

1

Như người nói trước đã tuyên bố - không, họ không được khởi tạo.

Đây thực sự là một nguồn cho các lỗi thực sự lạ như hệ điều hành hiện đại có xu hướng lấp đầy các vùng bộ nhớ mới được phân bổ bằng số không. Nếu bạn mong đợi điều đó, nó có thể làm việc lần đầu tiên. Tuy nhiên, khi ứng dụng của bạn tiếp tục chạy, các đối tượng delete -ing và new -ing, bạn sẽ sớm hay muộn kết thúc trong một tình huống mà bạn mong đợi số 0 nhưng một số không còn sót lại từ một đối tượng trước đó nằm.

Vì vậy, tại sao điều này sau đó, không phải là tất cả dữ liệu được phân bổ new mới? Có, nhưng không phải lúc nào cũng từ hệ điều hành. Hệ điều hành có xu hướng làm việc với các bộ nhớ lớn hơn (ví dụ: 4MB tại một thời điểm) vì vậy tất cả các phân bổ nhỏ một-ba-đây-ba-byte-có-và-deallocations được xử lý trong uyserspace, và do đó không zeroed ra.

PS. Tôi đã viết "có xu hướng", tức là bạn thậm chí không thể dựa vào thành công lần đầu tiên ...

16

Cho tất cả các mục đích thực tế - không.


Tuy nhiên đối với các triển khai tuân thủ về mặt kỹ thuật với tiêu chuẩn C++, câu trả lời phụ thuộc vào đối tượng là POD hay không và cách bạn khởi tạo. Theo chuẩn C++:

MyNonPodClass instance1;//built in members will not be initialized 
MyPodClass instance2;//built in members will be not be initialized 
MyPodClass* instance3 = new MyPodClass;//built in members will not be initialized 
MyPodClass* instance3 = new MyPodClass() ;//built in members will be zero initialized 

Tuy nhiên, trong thế giới thực, điều này không được hỗ trợ tốt do đó, không sử dụng nó.


Các bộ phận có liên quan của tiêu chuẩn là phần 8.5.5 và; 8.5.7

+0

Điều gì về globals, không phải lúc nào chúng cũng không được khởi tạo? – fredoverflow

+1

Đối với tất cả, nhưng đầu tiên, không có constructor mặc định được gọi là. Trong thực tế, ctors mặc định của họ làm như vậy (họ không khởi tạo bất cứ điều gì) - sau khi tất cả họ đều là cùng một lớp. Trong thứ tư, trình biên dịch chỉ có giá trị khởi tạo POD và không gọi hàm khởi tạo mặc định. –

+0

@FredOverflow, tất cả phạm vi không gian tên và các đối tượng tĩnh cục bộ hoặc lớp không được khởi tạo, không phụ thuộc vào kiểu của chúng (chúng có thể là các lớp phức tạp nhất ở đó - chúng sẽ không được khởi tạo). –

10

Tôi không hoàn toàn chắc chắn những gì bạn có ý nghĩa, nhưng:

struct A { int x; }; 

int a; // a is initialized to 0 
A b; // b.x is initialized to 0 

int main() { 
    int c;   // c is not initialized 
    int d = int(); // d is initialized to 0 

    A e;   // e.x is not initialized 
    A f = A();  // f.x is initialized to 0 
} 

Trong mỗi trường hợp, nơi tôi nói "không được khởi tạo" - bạn có thể thấy rằng trình biên dịch của bạn cung cấp cho nó một giá trị nhất quán, nhưng tiêu chuẩn không yêu cầu nó.

Rất nhiều vẫy tay được ném xung quanh, bao gồm cả tôi, về cách các kiểu tích hợp "có hiệu lực" có hàm tạo mặc định. Thực sự khởi tạo mặc định và khởi tạo giá trị được định nghĩa các thuật ngữ trong tiêu chuẩn, mà cá nhân tôi phải tra cứu mọi lúc. Chỉ có các lớp được định nghĩa trong tiêu chuẩn để có một hàm tạo ngầm mặc định.

135

Trình xây dựng mặc định ngầm định (bởi trình biên dịch) của một lớp không khởi tạo thành viên của các kiểu dựng sẵn.

Tuy nhiên, bạn phải ghi nhớ rằng trong một số trường hợp, việc khởi tạo thể hiện của lớp có thể được thực hiện bằng các phương tiện khác. Không phải bởi constructor mặc định, cũng không phải bởi constructor ở tất cả.

Ví dụ: có một niềm tin không chính xác phổ biến cho lớp C cú pháp C() luôn gọi hàm khởi tạo mặc định. Trong thực tế, cú pháp C() thực hiện cái gọi là khởi tạo giá trị của cá thể lớp. Nó sẽ chỉ gọi hàm tạo mặc định nếu nó là do người dùng khai báo. (Đó là trong C++ 03. Trong C++ 98 - chỉ khi lớp đó không phải là POD). Nếu lớp không có hàm tạo do người dùng khai báo, thì C() sẽ không gọi hàm dựng mặc định do trình biên dịch cung cấp, mà đúng hơn là sẽ thực hiện một kiểu khởi tạo đặc biệt không liên quan đến hàm tạo của C. Thay vào đó, nó sẽ trực tiếp giá trị khởi tạo mọi thành viên của lớp. Đối với các kiểu tích hợp, kết quả là không khởi tạo.

Ví dụ, nếu lớp học của bạn không có người sử dụng tuyên bố constructor

class C { 
    int x; 
}; 

sau đó trình biên dịch sẽ ngầm cung cấp một. Các nhà xây dựng trình biên dịch cung cấp sẽ không làm gì cả, có nghĩa là nó sẽ không khởi C::x

C c; // Compiler-provided default constructor is used 
// Here `c.x` contains garbage 

Tuy nhiên, khởi tạo sau sẽ zero-khởi x vì họ sử dụng rõ ràng () initializer

C c = C(); // Does not use default constructor for `C()` part 
      // Uses value-initialization feature instead 
assert(c.x == 0); 

C *pc = new C(); // Does not use default constructor for `C()` part 
       // Uses value-initialization feature instead 
assert(pc->x == 0); 

Các hành vi của () initializer là khác nhau trong một số khía cạnh giữa C++ 98 và C++ 03, nhưng không phải trong trường hợp này. Đối với lớp trên C, nó sẽ giống nhau: () trình khởi tạo thực hiện khởi tạo số không là C::x.

Một ví dụ về khởi tạo được thực hiện mà không liên quan đến xây dựng, tất nhiên, khởi tạo tổng hợp

C c = {}; // Does not use any `C` constructors at all. Same as C c{}; in C++11. 
assert(c.x == 0); 

C d{}; // C++11 style aggregate initialization. 
assert(d.x == 0); 
+4

LƯU Ý! Theo http://stackoverflow.com/a/3931589/18775 có một lỗi trong trình biên dịch Visual Studio C++ và C c = C(); có thể không phải lúc nào cũng hiệu quả. –

+13

Trong C++ 11: Liệu 'C c {}' khởi tạo 'x' bằng' 0'? – towi

+0

Tại sao trình biên dịch cảnh báo tôi rằng 'tm birthday {0,0,0, t, m-1, j-1900};' về việc thiếu các khởi tạo. Tôi thu thập g ++ - 4.8 với * "initializer mất tích cho thành viên 'tm :: tm_yday'" rằng giá trị là trái đơn vị - và giá trị không được khởi tạo bằng 0. Liệu '=' trước '{' có phải là một biện pháp khắc phục không? – towi

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