2011-10-28 26 views
14

Giả sử tôi có hai véc tơ và tôi di chuyển một véc tơ cho nhau, v1 = std::move(v2); v2 vẫn ở trạng thái có thể sử dụng sau này?Việc di chuyển có rời khỏi đối tượng trong trạng thái có thể sử dụng không?

+1

Điều này có vẻ giống như một bản sao của http://stackoverflow.com/q/7027523/576911. Xem câu trả lời này: http://stackoverflow.com/questions/7027523/what-can-i-do-with-a-moved-from-object/7028318#7028318 cho câu hỏi đó thảo luận về các hoạt động được phép về mặt điều kiện tiên quyết. –

Trả lời

22

Từ n3290, 17.6.5.15 Moved-từ trạng thái của các loại thư viện [lib.types.movedfrom]

  1. Đối tượng của các loại quy định tại Thư viện C++ chuẩn có thể được di chuyển từ (12,8) . Các thao tác di chuyển có thể được chỉ định rõ ràng hoặc được tạo ngầm. Trừ khi có quy định khác, các đối tượng chuyển từ đó phải được đặt ở trạng thái hợp lệ nhưng không xác định.

Kể từ khi nhà nước có giá trị, điều này có nghĩa bạn có thể an toàn hoạt động trên v2 (ví dụ bằng cách gán cho nó, mà sẽ đưa nó trở lại trạng thái nổi tiếng). Vì nó là không xác định, tuy nhiên, nó có nghĩa là bạn không thể ví dụ dựa trên bất kỳ giá trị cụ thể cho v2.empty() miễn là nó đang ở trong trạng thái này (nhưng gọi nó sẽ không sụp đổ chương trình). Lưu ý rằng tiên đề này của ngữ nghĩa di chuyển ("Di chuyển từ các đối tượng được để ở trạng thái hợp lệ nhưng không xác định") là một thứ mà tất cả mã nên cố gắng hướng tới (phần lớn thời gian), không chỉ các thành phần của Thư viện Chuẩn. Giống như ngữ nghĩa của các nhà xây dựng sao chép nên là tạo bản sao nhưng không được thực thi.

+0

+1, nhưng cách nó được viết, có vẻ như bạn không biết liệu 'v2' có rỗng sau' v2 = std :: vector {}; ' – Gabriel

+0

@Gabriel Tốt hay không, chỉnh sửa là theo thứ tự. –

7

Không, nó được để ở trạng thái không xác định.

Trích từ open-std-org bài viết -

.. move() cho mục tiêu giá trị của đối số của nó, nhưng là không bắt buộc phải duy trì giá trị của nguồn. Vì vậy, đối với một vectơ, di chuyển() có thể được dự kiến ​​sẽ để lại đối số của nó như là một vector có công suất bằng 0 để tránh phải sao chép tất cả các phần tử. Nói cách khác, di chuyển là một cách đọc có khả năng phá hoại.

+7

Nó nằm trong trạng thái không hợp lệ _but valid_. Tức là, bạn vẫn có thể sử dụng đối tượng theo cách chỉ có điều kiện tiên quyết mà đối tượng là hợp lệ. Ví dụ, bạn có thể gọi vector :: clear() trên đó chuyển từ vector để làm cho nó vào một trạng thái đã biết, và sau đó bắt đầu chèn các đối tượng vào nó. – bames53

+3

Nó __must__ hợp lệ. Nếu không thì điều gì sẽ xảy ra khi đối tượng vượt quá phạm vi.Nhiều khả năng nó sẽ không có bất cứ thứ gì trong kho dữ liệu của nó, nhưng bất kể nó là gì, nó sẽ hợp lệ. – Damon

+1

Có nhiều mức độ hợp lệ (trừu tượng). Theo như ngôn ngữ có liên quan, đối tượng sau khi di chuyển là hợp lệ khi đối tượng vẫn tồn tại, hàm hủy của nó có thể được gọi mà không gây ra hành vi không xác định, vv. . Ví dụ, thực tế là một vector đã trở thành zero-sized (không có dung lượng) là một vector C++ hợp lệ, nhưng một đối tượng có một phương thức đặt một phần tử cụ thể trên vectơ, mà không xác minh giả định (hiện đã bị vô hiệu hóa) vector phải có kích thước cụ thể, trở thành ... – rwong

0

Nếu bạn muốn sử dụng v2 sau khi di chuyển, bạn sẽ muốn làm điều gì đó như:

v1 = std::move(v2); 
v2.clear(); 

Tại thời điểm này, v1 sẽ có các nội dung ban đầu của v2 và v2 sẽ được trong một cái giếng trạng thái trống đã xác định. Điều này làm việc trên tất cả các container STL (và các chuỗi, cho rằng vấn đề), và nếu bạn đang thực hiện các lớp học của riêng bạn có hỗ trợ di chuyển ngữ nghĩa, có thể bạn sẽ muốn làm một cái gì đó tương tự.

Nếu việc triển khai STL thực sự cụ thể của bạn KHÔNG để đối tượng ở trạng thái trống, thì lệnh clear() thứ hai về cơ bản sẽ là một no-op. Trong thực tế, nếu đây là trường hợp, nó sẽ là một tối ưu hóa pháp lý cho một trình biên dịch để loại bỏ rõ ràng() sau khi di chuyển.

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