2009-03-06 29 views
860

Nếu 'Test' là một lớp học bình thường, là có bất kỳ sự khác biệt giữa:Làm các dấu ngoặc đơn sau tên loại có tạo sự khác biệt với mới không?

Test* test = new Test; 

Test* test = new Test(); 
+1

Điều này liên quan đến (nhưng không giống với) http://stackoverflow.com/questions/1613341/what-do-the-following-phrases-mean-in-c-zero-default-and-value-initializati –

+0

Chỉ cần sử dụng phép thử mới() để đảm bảo rằng nó được khởi tạo bằng không – Sung

Trả lời

836

Hãy nhận được sự khác biệt, vì có sự khác biệt thực sự ảnh hưởng đến hành vi của mã của bạn. Phần lớn những điều sau đây được lấy từ các bình luận được thực hiện cho một số "Old New Thing" article.

Đôi khi bộ nhớ được trả về bởi toán tử mới sẽ được khởi tạo và đôi khi nó không phụ thuộc vào kiểu bạn đang tạo mới là POD (plain old data) hoặc nếu đó là lớp chứa thành viên POD và đang sử dụng trình biên dịch -trình tạo mặc định được tạo ra.

  • Trong C++ 1998 có 2 loại khởi tạo: zero và mặc định
  • Trong C++ 2003, một loại thứ 3 của khởi tạo, giá trị khởi tạo đã được bổ sung.

Giả:

struct A { int m; }; // POD 
struct B { ~B(); int m; }; // non-POD, compiler generated default ctor 
struct C { C() : m() {}; ~C(); int m; }; // non-POD, default-initialising m 

Trong một trình biên dịch C++ 98, sau đây sẽ xảy ra:

  • new A - giá trị không xác định
  • new A() - zero-khởi

  • new B - xây dựng mặc định (B :: m chưa được định hình)

  • new B() - xây dựng mặc định (B :: m chưa được định hình)

  • new C - xây dựng mặc định (C :: m là zero-khởi tạo)

  • new C() - xây dựng mặc định (C :: m là zero-khởi tạo)

Trong C++ 03 trình biên dịch tuân thủ QTI, mọi thứ sẽ hoạt động như sau:

01.235.
  • new A - giá trị không xác định
  • new A() - giá trị khởi tạo A, đó là zero-khởi vì nó là một POD.

  • new B - mặc định-khởi (lá B :: m uninitialized)

  • new B() - giá trị khởi B mà zero-khởi tạo tất cả các lĩnh vực từ ctor mặc định của nó là trình biên dịch tạo ra như trái ngược với người dùng định nghĩa.

  • new C - mặc định khởi tạo C, gọi hàm ctor mặc định.

  • new C() - giá trị khởi tạo C, gọi hàm ctor mặc định.

Vì vậy, trong tất cả các phiên bản của C++, có sự khác biệt giữa new Anew A() vì A là POD.

Và có sự khác biệt về hành vi giữa C++ 98 và C++ 03 đối với trường hợp new B().

Đây là một trong những góc bụi của C++ có thể khiến bạn phát điên. Khi xây dựng một đối tượng, đôi khi bạn muốn/cần parens, đôi khi bạn hoàn toàn không thể có chúng, và đôi khi nó không quan trọng.

+0

Đối với 'new C' và' new C() 'trong C++ 03, là' m' left uninitialised? Còn về 'struct D {D(): {} int m; } '(tức là không phải POD do ctor do người dùng định nghĩa, nhưng m không được đề cập)? –

+0

Dường như cấu trúc 'struct D' của tôi đã được đề cập ở phần sau trong chuỗi chủ đề bình luận cũ mới! Đối với cả 'new D' và' new D() ',' m' không được khởi tạo. –

+4

@j_random_hacker, 'new A()' sẽ mặc định khởi tạo đối tượng trong C++ 98, giống như nó với 'new B()', 'new B',' new C() 'và' new C', nhưng * không * với 'mới A'. Đó là, khởi tạo mặc định luôn luôn được thực hiện trong C++ 98 khi một trong hai: 1) Lớp là một không POD và initializer là mất tích, hoặc 2) initializer là '()'. default-initialization zero-initializes đối tượng nếu nó là một POD, nhưng gọi hàm tạo mặc định cho các POD không. –

15

Không, họ đều giống nhau. Nhưng có một sự khác biệt giữa:

Test t;  // create a Test called t 

Test t(); // declare a function called t which returns a Test 

Đây là vì C cơ bản ++ (và C) quy tắc: Nếu một cái gì đó có thể có thể là một tuyên bố, sau đó nó là một bản tuyên bố.

Chỉnh sửa: Trả lại các vấn đề khởi tạo liên quan đến dữ liệu POD và không phải POD, trong khi tôi đồng ý với mọi thứ đã được nói, tôi chỉ muốn chỉ ra rằng những vấn đề này chỉ áp dụng nếu có điều gì mới hoặc nếu không được xây dựng không có một hàm tạo do người dùng định nghĩa. Nếu có một constructor như vậy, nó sẽ được sử dụng. Đối với 99,99% các lớp được thiết kế hợp lý, sẽ có một hàm tạo như vậy và do đó các vấn đề có thể bị bỏ qua.

+17

Lưu ý rằng đây là một điểm đặc biệt quan trọng vì dòng "Test t (5);" tương đương với "Test t = Test (5);" - nhưng "Kiểm tra t();" rất khác với "Test t = Test();". +1 – ojrac

+9

-1, tôi không đồng ý với tuyên bố của bạn rằng các vấn đề có thể bị bỏ qua. Bạn không cần phải biết các quy tắc một cách chính xác, nhưng bạn nên biết chúng trong trường hợp bạn phải tạo một lớp mới mà không có một hàm tạo mặc định do người dùng định nghĩa (sau đó bạn phải viết hàm khởi tạo hoặc tra cứu các quy tắc). – avakar

+10

-1 cho câu trả lời không chính xác đã biết. Chỉnh sửa của bạn bỏ qua sự hiện diện của mã được viết bởi các lập trình viên C cũ, những người không hiểu/sử dụng các nhà xây dựng. – Tom

10

Giả sử rằng thử nghiệm là một lớp với một hàm tạo được xác định, không có sự khác biệt. Dạng thứ hai làm cho nó rõ ràng hơn một chút mà hàm tạo của Test đang chạy, nhưng đó là về nó.

15

Nói chung, chúng tôi có khởi tạo mặc định trong trường hợp đầu tiên và khởi tạo giá trị trong trường hợp thứ hai.

Ví dụ: trong trường hợp với int (loại POD):

  • int* test = new int - chúng tôi có bất kỳ khởi và giá trị của * thử nghiệm có thể là bất kỳ.

  • int* test = new int() - * kiểm tra sẽ có giá trị 0.

hành vi tiếp theo phụ thuộc vào loại của bạn Kiểm tra. Chúng tôi có các trường hợp không đúng: Kiểm tra có hàm tạo mặc định, Kiểm tra đã tạo ra hàm khởi tạo mặc định, Kiểm tra chứa thành viên POD, thành viên không phải POD ...

44

new Thing(); là rõ ràng rằng bạn muốn có một hàm tạo được gọi là trong khi new Thing; được thực hiện để ngụ ý bạn không nhớ nếu constructor không được gọi.

Nếu được sử dụng trên cấu trúc/lớp với hàm tạo do người dùng xác định, không có sự khác biệt. Nếu được gọi trên cấu trúc/lớp tầm thường (ví dụ: struct Thing { int i; };) thì new Thing; giống như malloc(sizeof(Thing)); trong khi new Thing(); giống như calloc(sizeof(Thing)); - nó được khởi tạo không.

Gotcha nằm ở giữa:

struct Thingy { 
    ~Thingy(); // No-longer a trivial class 
    virtual WaxOn(); 
    int i; 
}; 

Hành vi của new Thingy; vs new Thingy(); trong trường hợp này thay đổi giữa C++ 98 và C++ 2003. Xem lời giải thích của Michael Burr về cách thức và lý do.

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