lỗi: sử dụng chức năng đã xóa


121

Tôi đang làm việc trên một số mã C ++ mà một người bạn đã viết và tôi gặp lỗi sau mà tôi chưa từng gặp trước đây khi biên dịch với gcc4.6:

error: use of deleted function

GameFSM_<std::array<C, 2ul> >::hdealt::hdealt()’ is implicitly deleted because the default definition would be ill-formed:
uninitialized non-static const member const h_t FlopPokerGameFSM_<std::array<C, 2ul> >::hdealt::h

Chỉnh sửa: Điều này đến từ một phần của mã sử dụng boost MSM: Boost Webpage

Edit2: Không được = delete()sử dụng ở bất kỳ đâu trong mã nguồn.

Nói chung, lỗi này có nghĩa là gì? Tôi nên tìm gì khi loại lỗi này xảy ra?


4
và mã bạn đang biên dịch?
ColWhi

Tôi chỉ tự hỏi lỗi có nghĩa là gì? Tôi có cần đăng mã cho điều đó không?
tàu con thoi 87

1
gcc.gnu.org/bugzilla/show_bug.cgi?id=47417 có thể hữu ích, bạn cũng đang sử dụng boost phải không?
ColWhi

@Sasquiha, vâng, tôi đang sử dụng boost MSM.
tàu con thoi 87

20
Vì đây là kết quả phù hợp đầu tiên của Google cho loại lỗi này - không phải trường hợp ở đây, nhưng nguyên nhân thông thường nhất cho loại lỗi này là sau khi bạn thêm một số hàm tạo tùy chỉnh vào một lớp - kết quả là trình biên dịch ngừng tạo hàm tạo mặc định và nếu một thể hiện của lớp đã từng được tạo thông qua hàm tạo mặc định, lỗi này sẽ xuất hiện. Chỉ cần thêm hàm tạo mặc định một cách rõ ràng.
SF.

Câu trả lời:


170

Thông báo lỗi nói rõ rằng hàm tạo mặc định đã bị xóa ngầm . Nó thậm chí còn cho biết tại sao: lớp chứa một biến const, không tĩnh, sẽ không được khởi tạo bởi ctor mặc định.

class X {
    const int x;
};

Kể từ khi X::xconst, nó phải được khởi tạo - nhưng một ctor mặc định thường không khởi tạo nó (vì nó là một loại POD). Do đó, để có được một ctor mặc định, bạn cần phải tự xác định một ctor (và nó phải khởi tạo x). Bạn có thể gặp phải tình huống tương tự với một thành viên tham khảo:

class X { 
    whatever &x;
};

Có lẽ cần lưu ý rằng cả hai điều này cũng sẽ vô hiệu hóa việc tạo ngầm định toán tử gán, về cơ bản cùng một lý do. Toán tử gán ngầm thường thực hiện việc gán thành viên một cách khôn ngoan, nhưng với một thành viên const hoặc thành viên tham chiếu, nó không thể làm điều đó vì không thể gán thành viên. Để thực hiện công việc phân công, bạn cần phải viết toán tử phân công của riêng mình.

Đây là lý do tại sao một constthành viên thường phải là tĩnh - khi bạn thực hiện một nhiệm vụ, bạn không thể chỉ định thành viên const. Trong trường hợp điển hình, tất cả các phiên bản của bạn sẽ có cùng một giá trị nên chúng cũng có thể chia sẻ quyền truy cập vào một biến duy nhất thay vì có nhiều bản sao của một biến sẽ có cùng giá trị.

Tất nhiên, có thể tạo các cá thể với các giá trị khác nhau - bạn (ví dụ) chuyển một giá trị khi bạn tạo đối tượng, vì vậy hai đối tượng khác nhau có thể có hai giá trị khác nhau. Tuy nhiên, nếu bạn cố gắng làm điều gì đó như hoán đổi chúng, thành viên const sẽ giữ nguyên giá trị ban đầu của nó thay vì bị hoán đổi.


@Jeffry Coffin: Thông báo lỗi thực sự được đăng dưới dạng chỉnh sửa, Thông báo lỗi ban đầu chỉ được đăngC++ error: use of deleted function
Alok Lưu

1
@Als: Xin lỗi, tôi có lẽ nên nói rõ rằng tôi không có ý định đó là một sự xúc phạm hoặc bất cứ điều gì theo lệnh đó, chỉ là những gì hiện có đã làm rõ ràng rằng những câu trả lời đó là không đúng.
Jerry Coffin

Không sao, tôi không cố ý cứng rắn ... Câu trả lời của bạn thật tuyệt vời và giải thích tình huống tốt nhất. +1 từ tôi :)
Alok Lưu

Tôi cho rằng bạn có thể giúp tôi giải quyết vấn đề của tôi ở đây vui lòng: stackoverflow.com/questions/23349524/…
Saher Ahwal

2
@OllieFord: Điều đó phụ thuộc. Điều gì sẽ xảy ra nếu (ví dụ) bạn gán một đối tượng có một giá trị trong trường đó cho một đối tượng khác có giá trị khác trong trường đó? Nếu nó phải được ghi đè, thì nó không thể là const. Nếu điều đó hoàn toàn không được phép, thì giá trị có thể thực sự là một phần của kiểu (ví dụ: tham số mẫu, nếu được biết tại thời điểm biên dịch).
Jerry Coffin

11

Bạn đang sử dụng một chức năng, được đánh dấu là deleted.
Ví dụ:

int doSomething( int ) = delete;

Dấu = xóa là một tính năng mới của C ++ 0x. Nó có nghĩa là trình biên dịch sẽ ngay lập tức ngừng biên dịch và khiếu nại "chức năng này bị xóa" khi người dùng sử dụng chức năng đó.

Nếu gặp lỗi này, bạn nên kiểm tra lại phần khai báo hàm cho =delete.

Để biết thêm về tính năng mới này được giới thiệu trong C ++ 0x, hãy xem phần này .


7
Vì tò mò, khi nào làm điều gì đó như vậy sẽ hữu ích?
Pepe

@Peter: để ngăn chuyển đổi ngầm.
R. Martinho Fernandes

7
Trên thực tế, nó nói "bị xóa ngầm vì ..." , ví dụ trên sẽ rõ ràng.
Georg Fritzsche

@Peter R: có vẻ như đây là một ví dụ: en.wikipedia.org/wiki/…
thoi87

1
@Downvoter: Thông báo lỗi thực sự được đăng dưới dạng chỉnh sửa, Thông báo lỗi ban đầu chỉ được đăngC++ error: use of deleted function
Alok Lưu

4

gcc 4.6 hỗ trợ một tính năng mới của các hàm đã xóa, nơi bạn có thể viết

hdealt() = delete;

để tắt hàm tạo mặc định.

Ở đây, trình biên dịch rõ ràng đã thấy rằng không thể tạo một phương thức khởi tạo mặc định, và hãy làm =deleteđiều đó cho bạn.


2

Tôi đã gặp lỗi này khi kế thừa từ một lớp trừu tượng và không triển khai tất cả các phương thức ảo thuần túy trong lớp con của mình.


1
Tương tự, tôi nhận được điều tương tự bằng cách bắt nguồn public virtualtừ lớp cơ sở cấp 2 trong đó lớp cơ sở cấp 1 có hàm tạo mặc định đã bị xóa rõ ràng. Việc xóa đã virtualkhắc phục sự cố mà không cần phải thực hiện tất cả các phương pháp.
Maitre Bart

1

Trong tiêu chuẩn C ++ 0x hiện tại, bạn có thể tắt rõ ràng các hàm tạo mặc định bằng cú pháp xóa, ví dụ:

MyClass() = delete;

Gcc 4.6 là phiên bản đầu tiên hỗ trợ cú pháp này, vì vậy có thể đó là vấn đề ...


Gcc 4.6 is the first version to support this syntaxTôi đoán điều đó sẽ giải thích tại sao tôi chưa từng thấy nó trước đây vì tôi mới bắt đầu sử dụng gcc4.6 gần đây.
tàu con thoi 87

2
Tôi đã sử dụng cú pháp này với GCC 4.5 trong nhiều năm. Ý tôi là ngày.
R. Martinho Fernandes

À, chắc hẳn tôi đã nghĩ đến các ctors được ủy quyền trong GCC 4.6.
jarmond

1

Việc chuyển từ gcc 4.6 sang gcc 4.8 đã giải quyết được vấn đề này cho tôi.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.