Code:Move thế hệ chức năng thành viên
#include <iostream>
#include <ios>
#include <string>
#include <type_traits>
#include <memory>
struct value
{
~value() = default;
std::unique_ptr<std::string> s;
};
int main()
{
std::cout << std::boolalpha;
std::cout << std::is_move_constructible<value>::value << '\n';
std::cout << std::is_move_assignable<value>::value << '\n';
using str_ptr = std::unique_ptr<std::string>;
std::cout << std::is_move_constructible<str_ptr>::value << '\n';
std::cout << std::is_move_assignable<str_ptr>::value << '\n';
return 0;
}
Output (biên soạn với g ++ v4.7.2, http://ideone.com/CkW1tG):
false false true true
Như tôi đã mong đợi, value
không được di chuyển constructible và không di chuyển nhượng vì :
~value() = default;
là do người dùng khai báo destructor, ngăn chặn thế hệ ngầm của các thành viên di chuyển theo phần 12.8 (xem bên dưới). Nếu destructor được lấy ra thì value
sẽ chuyển động và có thể chuyển nhượng được, như tôi mong đợi (http://ideone.com/VcR2eq).
Tuy nhiên, khi định nghĩa của value
được thay đổi thành (http://ideone.com/M8LHEA):
struct value
{
~value() = default;
std::string s; // std::unique_ptr<> removed
};
đầu ra là:
true true true true
value
được bất ngờ di chuyển constructible và di chuyển nhượng. Tôi có hiểu nhầm hay đây là lỗi trình biên dịch?
nền: Tôi cung cấp một câu trả lời cho câu hỏi this và đã được thông báo rằng Tree<>
là di chuyển, nhưng tôi không chắc chắn và đang cố gắng để xác định chắc chắn nếu nó là hay không.
Mục 8.4.2 chức năng Rõ ràng-defaulted của tiêu chuẩn C++ 11 (dự thảo n3337):
chức năng Rõ ràng-defaulted và chức năng ngầm-tuyên bố đang gọi chung là chức năng defaulted và việc triển khai sẽ cung cấp các định nghĩa ngầm định cho chúng (12.1 12.4, 12.8), có nghĩa là xác định chúng là đã bị xóa. Một chức năng thành viên đặc biệt được người dùng cung cấp nếu nó được người dùng khai báo và không được mặc định hoặc xóa một cách rõ ràng trên khai báo đầu tiên của nó. Chức năng mặc định do người dùng cung cấp (tức là, được mặc định rõ ràng sau lần khai báo đầu tiên) được xác định tại thời điểm được đặt mặc định rõ ràng; nếu một hàm như vậy được định nghĩa ngầm định là đã bị xóa, chương trình không đúng định dạng. [Ghi chú: Khai báo một chức năng như mặc định sau khi khai đầu tiên của nó có thể cung cấp thực hiện hiệu quả và định nghĩa ngắn gọn trong khi cho phép một giao diện nhị phân ổn định để một mã tiến hóa base.-end note]
Mục 12.8 Sao chép và di chuyển các đối tượng lớp (điểm 9):
If the definition of a class X does not explicitly declare a move constructor, one will be implicitly declared as defaulted if and only if - X does not have a user-declared copy constructor, - X does not have a user-declared copy assignment operator, - X does not have a user-declared move assignment operator, - X does not have a user-declared destructor, and - the move constructor would not be implicitly defined as deleted.
+1 Cảm ơn, giải thích rất rõ ràng. Trong sự tò mò, bạn có biết về bất kỳ đặc điểm nào kiểm tra một cách rõ ràng cho sự hiện diện của các thành viên di chuyển không? – hmjd
Không có. [_ "ngữ nghĩa ngôn ngữ cốt lõi không thực sự hữu ích đối với người viết thư viện, họ không quan tâm một lớp có thứ gì đó mà ngôn ngữ cốt lõi xem xét một nhà xây dựng bản sao hay không. Họ muốn biết nếu thực sự viết T (someT) sẽ hoạt động, cho dù nó gọi là một hàm tạo bản sao hoặc một hàm tạo di chuyển hoặc một hàm tạo thành viên hay bất kỳ hàm tạo nào. "_] (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/ n3142.html) Tuy nhiên, bạn có thể kiểm tra 'is_move_constructible :: value &&! is_copy_constructible :: giá trị' –