2015-09-23 24 views
5

Tôi là một người mới C++ tương đối đang cố gắng chuyển đổi dự án hiện có từ con trỏ thô, bằng giao thức quản lý bộ nhớ phức tạp, sử dụng shared_ptr của C++ 11. Nói chung nó sẽ rất suôn sẻ, và tôi nghĩ rằng Tôi hiểu cách shared_ptr hoạt động theo ngữ nghĩa di chuyển, tham chiếu rvalue, v.v.Lỗi lạ khi cố gắng thực hiện hoán đổi shared_ptr()

Tuy nhiên, tôi đã gặp lỗi lạ mà tôi không hiểu và không biết cách khắc phục. Một nền nhỏ đầu tiên. Tôi có một hệ thống phân cấp lớp bắt nguồn từ một lớp cơ sở trừu tượng tên EidosValue, và một lớp có tên EidosValue_Int_vector là (gián tiếp) một lớp con cụ thể về điều đó:

class EidosValue 
class EidosValue_Int : public EidosValue 
class EidosValue_Int_vector : public EidosValue_Int 

Mã của tôi nói chung là khả năng kiếm trong EidosValue, nhưng đôi khi, đặc biệt là khi tạo giá trị mới, tôi cần phải xử lý một lớp con cụ thể.

Tôi đã làm typedefs cho shared_ptr s cho những lớp này, vì vậy tôi có:

typedef std::shared_ptr<EidosValue> EidosValue_SP; 
typedef std::shared_ptr<EidosValue_Int_vector> EidosValue_Int_vector_SP; 

số những người khác. OK, vậy bây giờ là cốt lõi của vấn đề. Tôi có một hàm trả về một số EidosValue_SP mà nó tạo ra. Tùy thuộc vào logic trong hàm, nó có thể tạo ra một trong các lớp con cụ thể khác nhau của EidosValue. Vì vậy, tôi làm như sau:

EidosValue_SP MyClass::MyMethod(...) 
{ 
    EidosValue_SP result; 

    if (...) 
    { 
     EidosValue_Int_vector_SP int_result_SP = make_shared<EidosValue_Int_vector>(); 
     ... do subclass-specific stuff with int_result_SP... 
     result.swap(int_result_SP); 
    } 
    else (...) 
    { 
     ...similar logic for other subclasses... 
    } 

    ...other shared logic... 
    return result; 
} 

Sự cố với cuộc gọi swap(). Tôi gặp lỗi: "Non-const lvalue reference to type 'shared_ptr<EidosValue>' cannot bind to a value of unrelated type 'shared_ptr<EidosValue_Int_vector>'". Điều này là khó hiểu vì EidosValue_Int_vector không phải là một "loại không liên quan", nó là một lớp con công của EidosValue, và mã ở đây biết điều đó. Nếu tôi gõ result = make_shared<EidosValue_Int_vector>(); trình biên dịch không có vấn đề gì với điều đó, vì vậy nó rõ ràng biết rằng các loại có liên quan và tương thích. Nó chỉ không thích nó trong bối cảnh swap() vì một lý do nào đó. Ở những nơi khác trong dự án của tôi, tôi đã có thể chỉ đơn giản là làm một return int_result_SP;, với một loại trả về khai báo của EidosValue_SP, và điều đó đã làm việc tốt - trình biên dịch rất vui khi xem xét một EidosValue_Int_vector_SP là một EidosValue_SP trong ngữ cảnh đó - nhưng tôi có thể ' t làm điều đó ở đây vì logic được chia sẻ ở dưới cùng của hàm.

Tôi phần nào bị ràng buộc trong việc triển khai ở đây vì mã này là nút cổ chai và cần chạy nhanh (và có, tôi biết rằng từ thực sự thiết kế mã, và vâng, nó thực sự quan trọng). Vì vậy, điều quan trọng là sử dụng make_shared để tránh phân bổ kép và tôi cũng muốn tránh tăng/giảm số lần truy cập khi tôi đưa con trỏ từ int_result_SP đến kết quả; Tôi không muốn có một chút thời gian khi có hai shared_ptrs trỏ đến cá thể mới. Vì vậy, swap() có vẻ như là cách rõ ràng để đi; nhưng tôi bị chặn bởi lỗi trình biên dịch này. Tại sao nó xảy ra và làm thế nào tôi có thể sửa nó? Cảm ơn!

THÊM:

Ồ, cân nhắc thêm về điều này Tôi đặt cược Tôi biết tại sao lỗi xảy ra. swap() không phản đối việc đặt EidosValue_Int_vector vào số EidosValue_SP, nhưng không có vấn đề với việc đặt EidosValue vào EidosValue_Int_vector_SP; theo hướng đó các loại không tương thích. Tôi đã không nghĩ về nó theo cách đó kể từ khi result không có giá trị (tức là có nullptr, tôi đoán) trong đó; nhưng tất nhiên swap() không biết điều đó. OK, do đó, nếu đó là vấn đề, câu hỏi vẫn còn: làm thế nào tôi có thể thực hiện việc chuyển giao trong khi giữ mã nhanh - không làm một refcount inc/dec và không di chuyển ra khỏi việc sử dụng make_shared?Bây giờ tôi hiểu được vấn đề (tôi nghĩ) có vẻ như có khả năng rằng đó chỉ là một số API hoặc lừa mà tôi đã bỏ qua ...

Trả lời

4

Đây chính xác là những gì std::move dành cho. Sử dụng:

result = std::move (int_result_SP); 
5

Bạn không thể swap bởi vì, mặc dù EidosValue_Int_vectorlà mộtEidosValue các isn ngược' t đúng.

+0

Vâng, tôi đã tìm ra điều đó ngay sau khi tôi nhấp vào bài đăng. Xem phụ lục tôi vừa đưa lên. Câu hỏi vẫn là cách làm cho mã của tôi hoạt động. – bhaller

+2

chỉ 'result = int_result_SP;'. Không cần trao đổi – qehgt

+0

"trong khi vẫn giữ mã nhanh" - điều gì khiến bạn nghĩ rằng nhiệm vụ đang làm cho mã của bạn ** không ** nhanh? – YePhIcK

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