2011-08-29 22 views
8

Tôi đã xem xét các tính năng mới của C++ 11 và một trong số chúng gây nhầm lẫn cho tôi, vì tôi không thể tìm ra cách sử dụng nó trong thế giới thực.Các hàm bị xóa và mặc định Các ví dụ trên thế giới thực

Chức năng bị xóa và mặc định của nó, có ai có ví dụ thực tế về việc sử dụng hay chỉ là một trong những tính năng chỉ bổ sung một số đường?

Trả lời

8
struct A 
{ 
    A(const A& arg) : data(arg.data) 
    { 
    do_something_special(); 
    } 

    // by writing copy constructor, we suppress the generation of 
    // implicit default constructor A::A() 

    int data; 
}; 

void foo1() 
{ 
    A a; // does not work, since there's no default constructor 
} 

Hãy nói rằng constructor mặc định của chúng tôi không làm bất cứ điều gì đặc biệt và là (nhiều hơn hoặc ít hơn) bằng để trình biên dịch tạo ra một. Chúng tôi có thể sửa chữa nó bằng một trong hai cách viết constructor mặc định của chúng ta (mà có thể nhận được tẻ nhạt nếu lớp của chúng ta có nhiều thành viên không tĩnh), hoặc bằng cách sử dụng các = default cú pháp:

struct A 
{ 
    A() = default; 
    A(const A& arg) : data(arg.data) 
    { 
    do_something_special(); 
    } 

    int data; 
}; 

Xóa chức năng rất hữu ích khi chúng ta muốn cấm sử dụng các tình trạng quá tải hoặc mẫu chuyên biệt cụ thể hoặc chỉ để cấm các đối tượng sao chép (hoặc di chuyển).

void foo(char c) {} 
void foo(int i) = delete; // do not allow implicit int -> char conversion 

Khi bạn muốn cấm sao chép (ví dụ: đối tượng thread), cách thành ngữ thông thường là để khai báo constructor sao chép tin mà không cần thực hiện (yeah, hoặc sử dụng tăng :: noncopyable). Trong khi điều này làm việc cho hầu hết các trường hợp, đôi khi bạn có thể gặp phải một số lỗi liên kết tối nghĩa. Hãy xem xét:

struct A 
{ 
    A() = default; 

    friend void foo(); 

private: 
    A(const A&); 
}; 

void foo() 
{ 
    A a; 
    A b(a); // results in linker error in gcc 
} 

Xóa A(const A&) xóa, chúng tôi tránh lỗi liên kết tiềm ẩn và thực hiện ý định của chúng tôi (không cho phép sao chép) rất rõ ràng.

9

Chức năng thành viên đặc biệt do người dùng khai báo không phải là nhỏ. Nếu một lớp có bất kỳ hàm thành viên đặc biệt nontrivial, lớp không phải là POD. Vì vậy, loại này là POD:

struct S { 
    S() = default; 
    S(int) { } 
}; 

nhưng loại này không phải là POD:

struct S { 
    S() { } 
    S(int) { } 
}; 
+0

@Christian: Nếu chúng ta chỉ đơn giản là có 'struct S {S (int) {}}; ', sự hiện diện của' S (int) 'sẽ ngăn chặn hàm tạo mặc định được khai báo ngầm định. –

+0

Các quy tắc cho POD đã được thoải mái trong C++ 0x/11 vì vậy ví dụ thứ hai của bạn cũng sẽ là một POD trong C++ 0x/11. Bạn cũng có thể sử dụng các đặc điểm mới :: is_pod để tự kiểm tra bằng một khẳng định tĩnh chẳng hạn. – David

+0

@David: Các quy tắc cho POD thực sự đã được thư giãn, nhưng thứ hai 'S' vẫn không phải là POD. Cấu trúc POD phải là một lớp tầm thường. Một lớp tầm thường phải có một hàm tạo mặc định tầm thường. Một hàm tạo mặc định do người dùng cung cấp không phải là tầm thường. Chữ 'S' thứ hai có một hàm tạo mặc định do người dùng cung cấp và do đó không phải là POD. –

1

Bạn sẽ sử dụng các hàm đã xóa cho các lớp mà bạn muốn ngăn sao chép hoặc tạo tức thời trực tiếp (ví dụ: một singleton mà bạn muốn thực hiện hàm get_instance()). Bạn lạnh cũng sử dụng xóa để ngăn chặn các biến thể nhất định của hàm tạo của bạn.

Mặc định là hữu ích nếu bạn muốn trình biên dịch tạo ra hàm tạo cho bất kỳ trình tạo ngầm nào được tạo ra một cách ngầm định. Ví dụ nếu bạn tạo một hàm tạo đối số tùy chỉnh, trình tạo đối số mặc định sẽ không được trình biên dịch tạo ra để bạn có thể yêu cầu nó được tạo cho bạn với từ khóa mặc định.

Xem ở đây cho các ví dụ ở trên

http://www2.research.att.com/~bs/C++0xFAQ.html#default

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