hmj*_*mjd 12 c++ language-lawyer c++11
码:
#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;
}
Run Code Online (Sandbox Code Playgroud)
输出(使用g ++ v4.7.2编译,http://ideone.com/CkW1tG ):
false false true true
正如我所料,value不是可移动的,也不是可移动的,因为:
~value() = default;
Run Code Online (Sandbox Code Playgroud)
是一个用户声明的析构函数,它根据第12.8节(见下文)阻止隐式生成移动成员.如果析构函数被删除,那么value就像我期望的那样(http://ideone.com/VcR2eq)可移动构造并移动可分配.
但是,当定义value更改为(http://ideone.com/M8LHEA)时:
struct value
{
~value() = default;
std::string s; // std::unique_ptr<> removed
};
Run Code Online (Sandbox Code Playgroud)
输出是:
true true true true
value意外地移动可构造并移动可分配.我误解了还是编译错误?
背景:我提供了这个问题的答案,并被告知Tree<>可移动,但我不确定,并试图确定是否是.
第8.4.2节c ++ 11标准(草案n3337)的明确默认功能:
显式默认函数和隐式声明函数统称为默认函数,实现应为它们提供隐式定义(12.1 12.4,12.8),这可能意味着将它们定义为已删除.如果特殊成员函数是用户声明的,并且在其第一个声明中未明确默认或删除,则由用户提供.用户提供的显式默认函数(即,在第一次声明后显式默认)是在明确默认的位置定义的; 如果将这样的函数隐式定义为已删除,则该程序格式错误.[注:声明其第一声明之后为缺省的一个功能,可以提供高效的执行和简明的定义,同时使稳定的二进制接口到一个不断发展的代码base.端音符]
12.8节复制和移动类对象(第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.
std::is_move_constructible<T>如果iff std::is_constructible<T, T&&>为true,则为true,但这并不意味着这样的构造将调用移动构造函数,只是可以从相同类型的rvalue构造类型.这样的构造可能使用复制构造函数.
何时value::s是unique_ptr类型的复制构造函数和复制赋值运算符被定义为已删除,因为该s成员不可复制.它没有移动构造函数和移动赋值运算符,因为正如您所指出的,它具有用户声明的析构函数.这意味着它没有复制构造函数,也没有移动构造函数(也没有其他用户定义的构造函数可以接受类型的参数value&&),所以它std::is_constructible<value, value&&>是假的.
当value::s在一个string类型的拷贝构造函数和拷贝赋值运算符是 没有定义为删除,因为s成员是可复制,因此value也可复制和可复制构造类型也是MoveConstructible,因为它是在这种情况下有效:
value v1;
value v2 = std::move(v1); // calls copy constructor
Run Code Online (Sandbox Code Playgroud)
这意味着std::is_constructible<value, value&&>是真的,即使它调用复制构造函数而不是移动构造函数.
| 归档时间: |
|
| 查看次数: |
599 次 |
| 最近记录: |