2009-05-05 30 views
19

C++ 11 thêm khả năng cho trình biên dịch biết create a default implementation của bất kỳ số special member functions nào. Trong khi tôi có thể thấy giá trị của việc xóa một hàm, thì giá trị của một hàm mặc định rõ ràng ở đâu? Chỉ cần để trống và trình biên dịch sẽ làm việc đó.Điểm trong các hàm mặc định trong C++ 11 là gì?

Điểm duy nhất tôi có thể thấy là một constructor mặc định chỉ được tạo ra khi không có constructor khác tồn tại:

class eg { 
public: 
    eg(int i); 
    eg() = default; 
}; 

Nhưng là thực sự tốt hơn so với cách bạn làm điều đó bây giờ?

class eg { 
public: 
    eg(int i); 
    eg() {} 
}; 

Hoặc tôi có thiếu trường hợp sử dụng không?

Trả lời

19

Nhà xây dựng mặc định sẽ có tuyên bố và tuyên bố đó sẽ tuân theo các quy tắc truy cập thông thường. Ví dụ. bạn có thể làm cho hàm tạo bản sao mặc định được bảo vệ. Nếu không có các khai báo mới này, các thành viên được tạo mặc định là công khai.

+5

[dig] Ngoài ra: việc xác định một số chức năng thành viên đặc biệt sẽ ngăn trình biên dịch khỏi mặc định những người khác, nhưng điều này có thể được kích hoạt lại với = mặc định. Ví dụ: nếu bạn triển khai hàm tạo bản sao tùy chỉnh thì hàm tạo mặc định sẽ không được tạo. Thay vì tự thực hiện nó, bạn có thể mặc định rõ ràng nếu điều đó là đủ. – boycy

1

Tôi nghi ngờ rằng việc có thể tạo mặc định tạo hàm tạo bản sao sẽ thực sự hữu ích. Tôi không thể nhìn thấy một sử dụng cho mặc định tạo ra constructor mặc định kể từ khi bạn nói việc thực hiện bạn gõ sẽ ngắn hơn.

0

Đối với tôi tính năng vô hiệu sẽ hữu ích, Đối với hầu hết các lớp tôi hiện đang tạo, tôi vô hiệu hóa việc sao chép & chuyển nhượng - sẽ có một tính năng mà trình biên dịch có thể nhận ra để làm điều này, thay vì tùy thuộc vào trình liên kết lỗi.

+1

Ngay cả bây giờ (C++ 98) bằng cách bắt nguồn từ một lớp non_copyable bạn có thể có trình biên dịch phát hiện các lỗi (ngay cả khi được sử dụng trong lớp chính nó) và không cần phải chờ đợi cho thời gian liên kết. – Motti

+1

Tôi không tin vào việc giới thiệu nguồn gốc để giải quyết các vấn đề như thế này. –

16

Những ví dụ từ Stroustrup's website có thể giúp bạn hiểu được những điểm:

mặc định và chức năng xóa - kiểm soát giá trị mặc định

Các thành ngữ phổ biến của "cấm sao chép" bây giờ có thể được thể hiện trực tiếp:

class X { 
    // ... 

    X& operator=(const X&) = delete; // Disallow copying 
    X(const X&) = delete; 
}; 

Ngược lại, chúng tôi cũng có thể nói icitly mà chúng tôi muốn để mặc định sao chép hành vi:

class Y { 
    // ... 
    Y& operator=(const Y&) = default; // default copy semantics 
    Y(const Y&) = default; 

}; 

Là rõ ràng về mặc định là rõ ràng là không cần thiết, nhưng ý kiến ​​để rằng hiệu lực thi hành và (tệ hơn) người dùng xác định một cách rõ ràng hoạt động sao chép có nghĩa là để cung cấp cho các mặc định hành vi là không phổ biến. Để nó vào trình biên dịch để thực hiện hành vi mặc định đơn giản hơn, ít bị lỗi hơn, và thường dẫn đến mã đối tượng tốt hơn. Cơ chế "mặc định" có thể được sử dụng cho bất kỳ chức năng nào có mặc định. Cơ chế "xóa" có thể được sử dụng cho bất kỳ chức năng nào. Ví dụ, chúng ta có thể loại bỏ một chuyển đổi không mong muốn như này:

struct Z { 
    // ... 

    Z(long long);  // can initialize with an long long 
    Z(long) = delete; // but not anything less 
}; 
+0

Tôi thực sự đã đặt câu hỏi sau khi đọc Câu hỏi thường gặp C++ 0x của BS, nhận xét "rõ ràng là không cần thiết" của tôi đã nhắc tôi đặt câu hỏi về toàn bộ vấn đề mặc định. – Motti

+7

Hm, bạn có thể sử dụng xóa = bất kỳ thứ gì nhưng không = mặc định. Có muốn viết "int main() = default; // Quay lại đọc StackOverflow" – MSalters

12

Cũng như thay đổi khả năng tiếp cận (private/bảo vệ) của các chức năng được tạo ra, bạn sẽ có thể để làm cho họ ảo.

struct S 
{ 
    virtual ~S(); 
    virtual S& operator=(const S&); 
}; 

S::~S() = default; 
S& S::operator=(const S&) = default; 

Các khía cạnh sau đây của các chức năng defaulted thể được sửa đổi:

  • truy cập (được thực hiện ngoài công lập)
  • ảo
  • rõ ràng (constructors)
  • thông số kỹ thuật ngoại lệ
  • const-ness của thông số

nhưng để làm như vậy, các hàm phải được xác định bên ngoài lớp (8.4.2/2 trong C++0x Final Committee Draft).

Phiên bản đề xuất ban đầu của Lawrence Crowl là here.

Cảm ơn Roger Pate để biết rõ và trích dẫn.

+0

Tại sao gcc 4.5.0 phát ra lỗi sau cho mã bạn đã đăng: 'virtual S :: ~ S()' đã khai báo virtual không thể được mặc định trong nội dung lớp – bpw1621

+0

@bpw: Bởi vì 8.4.2/2 (được kiểm tra trong N3092) rõ ràng cấm mã này. –

+0

@Roger Cảm ơn bạn đã làm rõ (ở nơi khác). Như bạn đã chỉ ra là bắt buộc, tôi đã định nghĩa các hàm bên ngoài lớp. –

2

1) Trình tạo ngầm được tạo ngầm hiện không phải là ảo. Vì vậy, bạn cần phải xác định chúng để làm cho chúng ảo, trong trường hợp đó chúng không hiệu quả. Với = mặc định, Bạn sẽ có cả ảo và hiệu quả như các trình phá hủy ngầm được tạo ra.

2) Họ sẽ có các chỉ định truy cập, ngược lại với những người được tạo ngầm.

3) Nếu bạn nội tuyến hàm tạo mặc định của bạn, lớp của bạn vẫn còn tầm thường.

Here is an article elaborating this new feature.

0

mặc định là hữu ích hơn cho bản sao-constructors nếu bạn có một lớp học với rất nhiều các thuộc tính. Ví dụ, nếu bạn có lớp này:

class MyClass { 
private: 
    int offset; 
    std::string name; 
    std::vector<Person*> relatives; 
    float weight; 
    MyClass* spouse; 
    Vehicle* car; 
    double houseArea; 
    Date birth; 
    Person* parents[2]; 

public: 
    /* Default constructor will be defined here */ 
}; 

thay vì định sao chép constructor theo cách này:

MyClass(const MyClass& that) : 
    offset(that.offset), 
    name(that.name), 
    relatives(that.relatives), 
    weight(that.weight), 
    spouse(that.spouse), 
    car(that.car), 
    houseArea(that.houseArea), 
    birth(that.birth), 
    parents(that.parents) 
{} 

bạn sẽ xác định theo cách này:

MyClass(const MyClass&) = default; 
+0

Các hàm tạo bản sao mặc định của Yeahbut được [tạo bởi trình biên dịch tự động] (http://en.wikipedia.org/wiki/Special_member_functions) – Motti

1

Xem mục 17 từ cuốn sách tuyệt vời của Scott Meyer "Effective Modern C++". Nó mô tả nhiều điều kiện theo đó các nhà xây dựng sao chép mặc định, các hoạt động sao chép và các hoạt động di chuyển được tạo ra (hoặc không được tạo ra).

Nói cách khác, trình biên dịch có thể không "làm điều đó". Nhưng nếu hàm thành viên đặc biệt mặc định có ý nghĩa, người dùng có thể sử dụng từ khóa "mặc định" để cho trình biên dịch biết rõ ràng để tạo ra một hàm mặc định nếu không không được tạo ra.

Từ Những điều cần nhớ vào cuối khoản 17:

  • Move hoạt động được tạo ra chỉ dành cho tầng lớp thiếu các hoạt động di chuyển khai báo rõ ràng, sao chép hoạt động, hoặc một destructor.

  • Trình tạo bản sao chỉ được tạo cho các lớp thiếu một hàm tạo bản sao được khai báo rõ ràng và được xóa nếu thao tác di chuyển được khai báo.Toán tử gán bản sao chỉ được tạo ra cho các lớp thiếu một toán tử gán bản sao được khai báo rõ ràng, và nó sẽ bị xóa nếu một thao tác di chuyển được khai báo. Việc tạo ra các hoạt động sao chép trong các lớp với một hàm hủy được khai báo rõ ràng sẽ không được chấp nhận nữa.

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