2016-03-16 18 views
6

Tôi có một lớp đại diện cho một bối cảnh thời gian chạy và xây dựng một cây, gốc cây được giữ trong một unique_ptr. Khi xây dựng cây được thực hiện, tôi muốn giải nén cây. Đây là cách có vẻ (không Runnable, đây không phải là một câu hỏi gỡ lỗi):std :: unique_ptr :: release() vs std :: move()

class Context { 
    private: 
    std::unique_ptr<Node> root{new Node{}}; 
    public: 
    // imagine a constructor, attributes and methods to build a tree 
    std::unique_ptr<Node> extractTree() { 
     return std::move(this->root); 
    } 
}; 

Vì vậy, tôi sử dụng std::move() để trích xuất các nút gốc từ Context dụ.

Tuy nhiên có một giải pháp thay thế cho việc sử dụng std::move() ví dụ .:

std::unique_ptr<Node> extractTree() { 
    // This seems less intuitive to me 
    return std::unique_ptr<Node>{this->root.release()}; 
} 

std::move() lựa chọn tốt nhất?

+0

Bạn cần gọi 'đặt lại' từ 'this-> root' sau khi di chuyển. Bạn nên đọc câu trả lời này tốt hơn http://stackoverflow.com/a/20850223/555515 – neuront

+2

@neuront: Không, bạn không biết. –

+0

sau khi di chuyển src chứa nullptr, reset là vô nghĩa! – paulm

Trả lời

4

bạn chắc chắn nên đi với phiên bản đầu tiên là phiên bản thứ hai về cơ bản thực hiện mọi thứ mà phiên bản đầu tiên làm với nhiều mã hơn và ít dễ đọc hơn.

nói về mặt triết học, phiên bản thứ hai di chuyển con trỏ duy nhất, không hơn, không kém. vậy tại sao lại đi vòng quanh bàn thay vì sử dụng số điện thoại đã sẵn có, dễ đọc hơn và độc đáo hơn std::unique_ptr(std::unique_ptr&&)?

và cuối cùng, nếu con trỏ thông minh của bạn ở một nơi nào đó trong tương lai sẽ giữ deleter trang phục, phiên bản đầu tiên sẽ đảm bảo deleter di chuyển, phiên bản thứ hai không di chuyển deleter. Tôi có thể tưởng tượng tưởng tượng lập trình xây dựng phi trang phục deleter con trỏ độc đáo ra khỏi costum-deleter unique_pointer với việc sử dụng release. với semtantics di chuyển, chương trình sẽ không biên dịch được.

3

Điều bạn đang làm là nguy hiểm. Khi bạn đã gọi số getTree(), bạn không được gọi đó lần thứ hai, điều này không rõ ràng từ giao diện. Bạn có thể muốn xem xét lại thiết kế của mình (ví dụ: shared_ptr có thể thực hiện công việc tốt hơn hoặc đơn giản là lưu gốc dưới dạng con trỏ thô và tự quản lý thỏa thuận).

Dù sao, sử dụng std::move là lựa chọn tốt hơn cho cả hai nếu bạn muốn gắn bó với thiết kế của bạn vì nó làm cho ý định của bạn rõ ràng hơn.

CHỈNH SỬA: dường như 'không được' có ý nghĩa đặc biệt về sự không chắc chắn bằng tiếng Anh mà tôi không biết. Bạn có thể gọi hàm hai lần hoặc nhiều lần tùy thích, nhưng sẽ không trả về một con trỏ tới một đối tượng hợp lệ nếu được thực hiện liên tiếp.

+0

Không có vấn đề gì khi gọi 'getTree()' lần thứ hai. Nó sẽ chỉ trả về một null 'unique_ptr'. –

+1

Tại sao bạn không gọi 'getTree() 'hai lần? Một khi gốc được di chuyển nó được đặt thành 'nullptr', do đó, di chuyển từ nó một lần nữa sẽ cho bạn một' nullptr', mà có vẻ giống như một hành vi rất hợp lý cho một đối tượng rỗng. – nwp

+0

là không lý do tại sao hes cho rằng bạn không gọi nó hai lần ... – AngryDuck

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