2016-11-17 20 views
7

Dưới đây là vấn đề tối giản của các mã:lỗi biên dịch khi destructor tuyên bố trong cơ thể của lớp với unique_ptr như thành viên của cùng một lớp

struct B { 
    B() = default; 
    //~B() {}; // error: use of deleted function ‘B& B::operator=(const B&)’ 
    std::unique_ptr<int> m_pB = nullptr; 
}; 

int main() 
{ 
    std::vector<B> vB; 
    vB.erase(vB.begin()); 
} 

Trên mã biên dịch tốt, trừ khi destructor là không chú thích. Đối với yêu cầu của tôi, tôi cần phải có một cơ thể của ~B() được xác định rõ ràng.

Làm thế nào tôi có thể xác định phần thân của hàm hủy với unique_ptr cùng tồn tại trong cùng một lớp?

Note: Cố gắng xác định = default phiên bản sao chép & constructor di chuyển vô ích. Trong mã thực sự của tôi, unique_ptr<int>unique_ptr<forward_declared_class>. Không thể xác định được vấn đề này trong SO, mặc dù tôi chắc chắn rằng nó phải có mặt. Vui lòng đánh dấu là dupe.

+0

Được chuyển tiếp tuyên bố có liên quan đến vấn đề - không thể gọi 'xóa' đáng tin cậy (tức là không thể khởi tạo' std :: default_deleter') mà không có trình phá hủy hiển thị. – milleniumbug

+0

Xem câu hỏi này http://stackoverflow.com/questions/6012157/is-stdunique-ptrt-required-to-know-the-full-definition-of-t – milleniumbug

+0

Không có lý do nào để gán nullptr cho m_pB. –

Trả lời

5

Có vẻ như mã của bạn đòi hỏi B được sao chép constructible và sao chép có thể chuyển nhượng cho std::vector (ít nhất là cho Visual C++, mà tôi thử nghiệm) .

Sao chép constructor và sao chép các nhà khai thác assignement chỉ có thể là = deletestd::unique_ptr (triển khai tuyên bố = default nên gây ra các chức năng để bị xóa theo), và, bằng cách thực hiện destructor, bạn vô hiệu hóa cài đặt mặc định của nhà xây dựng di chuyển và di chuyển toán tử gán.

Vì vậy, bạn cần khai báo rõ ràng toán tử gán di chuyển. Hãy thử:

#include <memory> 
#include <vector> 

struct B { 
    B() = default; 
    ~B() {} 
    B& operator=(B&&) = default; 
    std::unique_ptr<int> m_pB = nullptr; 
}; 

int main() 
{ 
    std::vector<B> vB; 
    vB.erase(vB.begin()); 
} 
3

Bạn có thể khai báo và triển khai toán tử di chuyển, mà trình biên dịch yêu cầu. Tất nhiên, nó phàn nàn về việc chuyển nhượng bản sao, nhưng một bản sao hợp lý dường như là không thể đối với cấu trúc của bạn.

Có thể, thông báo lỗi có một chút sai lệch vì việc triển khai thực hiện std::vector::erase có chứa một số thứ như _data[i-1] = _data[i] trong mã chọc các phần tử vectơ tới vị trí các mục đã xóa. Vì vậy, trình biên dịch cần bất kỳ toán tử gán nào và chúng tôi cung cấp nó với một toán tử chuyển động.

Ví dụ, điều này hoạt động tốt (gcc 4.8.3):

struct B { 
    B() = default; 
    B& operator=(B&& op) { 
    m_pB = std::move(op.m_pB); 
    return *this; 
    } 
    ~B() {}; // no more errors. 
    std::unique_ptr<int> m_pB = nullptr; 
}; 

int main() 
{ 
    std::vector<B> vB; 
    vB.erase(vB.begin()); 
} 
0

Mã vectơ là một cá trích đỏ.

Khi lớp U có thành viên kiểu unique_ptr, và T được chuyển tiếp khai báo, định nghĩa của hàm hủy phải nằm trong tệp cpp, khi U không còn là kiểu không hoàn chỉnh nữa.

Bạn phải có ~ U(); trong tiêu đề và trong tệp cpp có U :: ~ U() {} hoặc U :: ~ U() = mặc định;

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