2015-03-29 13 views
6

Tôi có một class A với biến thành viên _atomicVar loại std::atomic<int>.
lỗi C2280: cố gắng tham chiếu đến hàm đã xóa (nguyên tử <int>)

#include <atomic> 

class A 
{ 
public: 
    A(); 
    ~A(); 

private: 
    std::atomic<int> _atomicVar; 
}; 

Nếu tôi xây dựng dự án tôi nhận được lỗi sau:

error C2280: 'std::atomic<int>::atomic(const std::atomic<int> &)' : attempting to reference a deleted function 

tôi chủ yếu là một nhà phát triển C# vì vậy tôi không biết từng chi tiết của C++ (chưa). Tôi không biết nơi tôi sử dụng bản sao c'tor của atomic<int>.
Tôi cũng đã cố gắng để khởi tạo _atomicVar:

std::atomic<int> _atomicVar { 0 }; 

... nhưng điều đó không làm việc.
Tôi hy vọng rằng _atomicVar (không có khởi tạo rõ ràng) sẽ được khởi tạo với giá trị mặc định cho int.
Bạn có thể cho tôi biết tại sao lỗi này xảy ra không?

+0

Dường như bạn đang sử dụng Visual Studio. Phiên bản nào? Ngoài ra trên những dòng mã bạn nhận được lỗi? –

+2

Đó có phải là toàn bộ mã của bạn không? Có lẽ bạn đang sao chép các đối tượng 'A'? Có lẽ bạn sử dụng một container đòi hỏi các phần tử 'CopyConstructible'? – zch

+2

Đơn giản chỉ cần không xác định constructor sao chép là đủ lý do cho điều này xảy ra.Khi bạn định nghĩa các kiểu, có chứa các thành phần 'nguyên tử', bạn phải xác định rõ ràng ngữ nghĩa hợp lệ cho tất cả các hoạt động tiềm ẩn, có thể được trình biên dịch thực hiện hoặc chèn vào. –

Trả lời

14

Đó là do hàm tạo bản sao của std::atomicđã xóa.

Xem this documentation page.

Kể từ khi bạn không xác định rõ ràng constructor sao chép cho A, biên dịch tạo ra một mặc định, mà chỉ đơn giản gọi constructor sao chép cho tất cả các thành viên (mà không được phép cho std::atomic).

Giải pháp:

class A 
{ 
public: 
    A(); 
    A(const A& origin); // add this line 
    ~A(); 
private: 
    std::atomic<int> _atomicVar; 
}; 

A::A(const A& origin) 
: _atomicVar(0) //zero-initialize _atomicVar 
{ 
} 

EDIT

Nếu bạn tự hỏi, tại sao atomic loại không copyable, bạn có thể muốn đọc this question, đặc biệt là câu trả lời chấp nhận. Nếu bạn muốn sao chép giá trị của std::atomic, bạn có thể làm điều đó:

A::A(const A& origin) 
: _atomicVar(origin._atomicVar.load()) 
{ 
} 

Nhưng hãy nhớ, rằng đây hoạt động riêng của mình sẽ không phải là một một nguyên tử (và, đối với hầu hết logic, vô nghĩa).

Ngoài ra, bạn cũng có thể muốn xác định toán tử gán rõ ràng (hãy nhớ về Rule of Three).

Các lựa chọn tốt nhất cho hành vi đúng đắn của chương trình của bạn sẽ được xóa hai phương pháp:

class A 
{ 
public: 
    A(); 
    A(const A&) = delete; 
    ~A(); 

    A& operator=(const A&) = delete; 

private: 
    std::atomic<int> _atomicVar; 
}; 

Nếu trình biên dịch của bạn không hỗ trợ này (ví dụ bất kỳ VC trước VC12), tuyên bố họ là tư nhân và không cung cấp nội dung:

class A 
{ 
public: 
    A(); 
    ~A(); 

private: 
    //do not define these two 
    A(const A&); 
    A& operator=(const A&); 

private: 
    std::atomic<int> _atomicVar; 
}; 
+3

Ehm Tôi sẽ không làm điều này - bây giờ ngữ nghĩa sao chép của 'A' bị hỏng. Thay vào đó, tôi sẽ thay thế 'delete'' A''s copy constructor. –

+1

Vâng, bạn nói đúng. Tôi đã cập nhật câu trả lời của tôi khi bạn viết bài này. –

+0

Cảm ơn bạn @MateuszGrzejek điều này thực sự đã giúp tôi, tôi có một lớp học đã được instantiated bằng cách sử dụng shared_ptr, và lớp chính nó đã tổ chức một unique_ptr cho một tuyên bố về phía trước, tôi đã không hiểu lỗi tôi đã nhận được lúc đầu kể từ khi tôi cung cấp một mặc định destructor cần thiết để sử dụng một khai báo phía trước trong một unique_ptr, sau khi đọc nó và tạo thêm một constructor sao chép cho lớp để thiết lập unique_ptr nullptr cho đến khi hàm dựng đúng được gọi, mã của tôi làm việc, vì vậy cảm ơn cho một câu trả lời tốt đã giúp rất nhiều (= – daniel

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