移动成员函数生成 [英] Move member function generation

查看:131
本文介绍了移动成员函数生成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

代码:

#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;
}



输出(使用g ++ v4.7.2,http://ideone.com/CkW1tG ):


false
false
true
true



如我所料, value 不可移动构造,不能移动可分配,因为:

As I expect, value is not move constructible and is not move assignable because:

~value() = default;

是用户声明的析构函数,可防止隐式生成移动成员根据 12.8 部分(见下文)。
如果析构函数被删除,那么 value 是可移动构造的,并且如我预期的那样移动assignable( http://ideone.com/VcR2eq )。

is a user-declared destructor, which prevents the implicit generation of move members according to section 12.8 (see below). If the destructor is removed then value is move constructible and move assignable, as I expect (http://ideone.com/VcR2eq).

但是,当定义 value 更改为( http://ideone.com/M8LHEA ):

However, when the definition of value is changed to (http://ideone.com/M8LHEA):

struct value
{
    ~value() = default;
    std::string s;      // std::unique_ptr<> removed
};

输出为:


true
true
true
true

意外移动可构造和移动可分配。
我误解了还是这是一个编译器错误?

value is unexpectedly move constructible and move assignable. Am I misunderstanding or is this a compiler bug?

提供了问题的答案,并获悉 Tree<<> 是可移动的,但我不确定,我试图确定是否是否。

Background: I provided an answer to this question and was informed that Tree<> was moveable, but I am unsure and am attempting to determine for certain if it is or not.

部分

显式默认函数和隐式声明的函数是
,统称为默认函数,实现
为它们提供隐式定义(12.1 12.4,12.8),这可能意味着
将它们定义为已删除。
如果是用户声明的特殊成员函数是用户提供的,并且
在其第一个声明中没有显式默认或删除。
用户提供的显式默认函数(即,在第一次声明之后显式地默认
)定义在
显式默认的点;如果这样的函数隐式定义为删除,
程序是不成形的。 [注意:在
第一个声明之后声明一个函数是默认的可以提供有效的执行和简洁的定义,而
使一个稳定的二进制接口能够演变代码库。-end note]

Explicitly-defaulted functions and implicitly-declared functions are collectively called defaulted functions, and the implementation shall provide implicit definitions for them (12.1 12.4, 12.8), which might mean defining them as deleted. A special member function is user-provided if it is user-declared and not explicitly defaulted or deleted on its first declaration. A user-provided explicitly-defaulted function (i.e., explicitly defaulted after its first declaration) is defined at the point where it is explicitly defaulted; if such a function is implicitly defined as deleted, the program is ill-formed. [ Note: Declaring a function as defaulted after its first declaration can provide efficient execution and concise definition while enabling a stable binary interface to an evolving code base.—end note ]

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> 是true iff std :: is_constructible< T,T&> 是真的,但这并不意味着这样的结构会调用move构造函数,只有可能从相同类型的右值构造类型。

std::is_move_constructible<T> is true iff std::is_constructible<T, T&&> is true, but that doesn't imply that such a construction will call a move constructor, only that it is possible to construct the type from an rvalue of the same type. Such a construction might use a copy constructor.

value :: s unique_ptr 类型的拷贝构造函数和拷贝赋值运算符定义为已删除,因为 s 成员不可拷贝。它没有移动构造函数和移动赋值运算符,因为,如你所指出的,它有一个用户声明的析构函数。这意味着它没有复制构造函数和没有移动构造函数(没有其他用户定义的构造函数可以接受类型 value&& 的参数),因此 std :: is_constructible< value,value&> 为false。

When value::s is a unique_ptr the type's copy constructor and copy assignment operator are defined as deleted, because the s member is not copyable. It does not have a move constructor and move assignment operator because, as you pointed out, it has a user-declared destructor. That means it has no copy constructor and no move constructor (and no other user-defined constructors that could accept an argument of type value&&) so std::is_constructible<value, value&&> is false.

value :: s 是一个字符串类型的复制构造函数和复制赋值运算符定义为已删除,因为<$ c $ <> c> c>也可以复制,并且CopyConstructible类型也是MoveConstructible,因为 是<它在此上下文中有效:

When value::s is a string the type's copy constructor and copy assignment operator are not defined as deleted, because the s member is copyable, and so value is also copyable, and a CopyConstructible type is also MoveConstructible, because it's valid in this context:

value v1;
value v2 = std::move(v1);  // calls copy constructor

这意味着 std :: is_constructible< value,value& ;&> 是真的,即使它调用复制构造函数而不是move构造函数。

That means std::is_constructible<value, value&&> is true, even though it invokes the copy constructor not a move constructor.

这篇关于移动成员函数生成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆