std :: auto_ptr thành std :: unique_ptr


185

Với tiêu chuẩn mới sắp tới (và các bộ phận đã có sẵn trong một số trình biên dịch), loại mới std::unique_ptrđược cho là thay thế cho std::auto_ptr.

Việc sử dụng của chúng có trùng lặp chính xác không (vì vậy tôi có thể thực hiện tìm / thay thế toàn cầu trên mã của mình (không phải là tôi sẽ làm điều này, nhưng nếu tôi đã làm)) hoặc tôi có nên biết về một số khác biệt không rõ ràng khi đọc tài liệu không?

Ngoài ra nếu nó là một sự thay thế trực tiếp, tại sao lại đặt cho nó một cái tên mới thay vì chỉ cải thiện std::auto_ptr?

Câu trả lời:


219

Bạn không thể thực hiện tìm / thay thế toàn cầu vì bạn có thể sao chép auto_ptr(với các hậu quả đã biết), nhưng unique_ptrchỉ có thể được di chuyển. Bất cứ thứ gì trông giống như

std::auto_ptr<int> p(new int);
std::auto_ptr<int> p2 = p; 

sẽ phải trở thành ít nhất như thế này

std::unique_ptr<int> p(new int);
std::unique_ptr<int> p2 = std::move(p);

Đối với các khác biệt khác, unique_ptrcó thể xử lý các mảng một cách chính xác (nó sẽ gọi delete[], trong khi auto_ptrsẽ cố gắng gọi delete.


101
mặt khác, thực hiện tìm / thay thế này sẽ chỉ dẫn đến lỗi biên dịch, nó sẽ không âm thầm phá mã theo như tôi có thể thấy. Vì vậy, nó là an toàn để làm, nếu bạn sửa lỗi thủ công biên dịch sau đó
jalf

7
@jalf: Thật vậy, tôi không thể nghĩ ra một ví dụ ngược lại sẽ được xác định rõ với auto_ptrs và UB với unique_ptrs.
Cubbi

1
vì vậy có vẻ như unique_ptr là sự cải tiến của auto_ptr: mảng hỗ trợ & xóa bỏ sự mơ hồ
Baiyan Huang

92

std::auto_ptrstd::unique_ptrkhông tương thích trong một số ngày và giảm thay thế ở những người khác. Vì vậy, không tìm thấy / thay thế là không đủ tốt. Tuy nhiên, sau khi tìm / thay thế làm việc thông qua các lỗi biên dịch sẽ khắc phục mọi thứ trừ các trường hợp góc lạ. Hầu hết các lỗi biên dịch sẽ yêu cầu thêm a std::move.

  • Biến phạm vi chức năng:
    tương thích 100%, miễn là bạn không chuyển nó theo giá trị cho hàm khác.
  • Kiểu trả về:
    không tương thích 100% nhưng tương thích 99% không có vẻ sai.
  • Tham số chức năng theo giá trị:
    Tương thích 100% với một cảnh báo, unique_ptrs phải được chuyển qua một std::movecuộc gọi. Điều này là đơn giản vì trình biên dịch sẽ phàn nàn nếu bạn không hiểu đúng.
  • Tham số chức năng theo tham chiếu:
    tương thích 100%.
  • Biến thành viên lớp:
    Cái này là khó. std::auto_ptrngữ nghĩa sao chép là xấu. Nếu lớp không cho phép sao chép thì đó std::unique_ptrlà sự thay thế. Tuy nhiên, nếu bạn đã cố gắng cung cấp cho ngữ nghĩa sao chép hợp lý của lớp, bạn sẽ cần thay đổi std::auto_ptrmã xử lý. Điều này đơn giản vì trình biên dịch sẽ phàn nàn nếu bạn không hiểu đúng. Nếu bạn cho phép sao chép một lớp học với một std::auto_ptrthành viên mà không có bất kỳ mã đặc biệt nào, thì thật đáng xấu hổ cho bạn và chúc may mắn.

Tóm lại, std::unique_ptrlà một không gián đoạn std::auto_ptr. Nó không tuân theo các hành vi thời gian biên dịch thường là lỗi khi sử dụng a std::auto_ptr. Vì vậy, nếu bạn sử dụng std::auto_ptrvới sự chăm sóc cần thiết, việc chuyển đổi std::unique_ptrsẽ đơn giản. Nếu bạn dựa vào std::auto_ptrhành vi kỳ quặc của mình, thì dù sao bạn cũng cần phải cấu trúc lại mã của mình.


8
+1 cho "dù sao bạn cũng cần cấu trúc lại mã của mình". auto_ptrs chỉ tốt cho những gì 20.4.5 / 3 nói rằng chúng tốt cho.
Cubbi

8
Để tôi thêm vào điều này, bằng mọi cách, bạn nên thay thế auto_ptr bằng unique_ptr trong mã của bạn và sửa các lỗi biên dịch. Bạn sẽ ngạc nhiên khi có bao nhiêu lỗi này sẽ phát hiện ra.
Bartosz Milewski

36

AFAIK, unique_ptrkhông phải là một sự thay thế trực tiếp. Lỗ hổng lớn mà nó sửa chữa là chuyển quyền sở hữu ngầm.

std::auto_ptr<int> a(new int(10)), b;
b = a; //implicitly transfers ownership

std::unique_ptr<int> a(new int(10)), b;
b = std::move(a); //ownership must be transferred explicitly

Mặt khác, unique_ptrsẽ có những khả năng hoàn toàn mới: chúng có thể được lưu trữ trong các thùng chứa.


8
Scott Meyers cũng đã đề cập trong "Hiệu quả C ++" (Ấn bản thứ 3) Mục 13 (trang 64) của mình rằng các bộ chứa STL yêu cầu nội dung của chúng thể hiện hành vi sao chép "bình thường", vì vậy các thùng chứa auto_ptrkhông được phép.
Qiang Xu

31

Herb Sutter có một lời giải thích hay về GotW # 89 :

Thỏa thuận với auto_ptr là gì? auto_ptr được đặc trưng nhất là một nỗ lực dũng cảm để tạo ra unique_ptr trước khi C ++ có ngữ nghĩa di chuyển. auto_ptr hiện không được dùng nữa và không nên được sử dụng trong mã mới.

Nếu bạn có auto_ptr trong một cơ sở mã hiện có, khi bạn có cơ hội hãy thử thực hiện tìm kiếm và thay thế toàn cầu auto_ptr thành unique_ptr; phần lớn các sử dụng sẽ hoạt động như nhau và nó có thể phơi bày (như lỗi thời gian biên dịch) hoặc sửa chữa (âm thầm) một lỗi hoặc hai lỗi mà bạn không biết là mình đã mắc phải.

Nói cách khác, trong khi việc tìm kiếm và thay thế toàn cầu có thể tạm thời "phá vỡ" mã của bạn, bạn vẫn nên làm điều đó: Có thể mất một chút thời gian để sửa lỗi biên dịch, nhưng về lâu dài sẽ giúp bạn tránh được nhiều rắc rối hơn.


Liên kết tuyệt vời. Cảm ơn rất nhiều!
fotNelton
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.