从右值中删除move构造函数并构造对象 [英] Deleting move constructor and constructing object from rvalue

查看:115
本文介绍了从右值中删除move构造函数并构造对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图从"Effective Modern C ++"中了解关于特殊成员函数生成的第17项,因此,我尝试了一些示例并试图对某些行为进行推理.书中写着:

I'm trying to understand Item 17 from "Effective Modern C++" about special member function generation so I was trying some examples and am trying to reason about some behavior. In the book it says:

..当我引用移动操作移动构造或移动分配数据成员或基类时,不能保证实际上会发生移动.实际上,成员移动"更像是成员移动请求,因为未启用移动的类型(即,不提供对移动操作的特殊支持,例如,大多数C ++ 98旧类) "通过他们的复制操作. ... 此外,不会为任何显式声明复制操作的类生成移动操作.

..that when I refer to a move operation move-constructing or move-assigning a data member or base class, there is no guarantee that a move will actually take place. "Memberwise moves" are, in reality, more like memberwise move requests, because types that aren’t move-enabled (i.e., that offer no special support for move operations, e.g., most C++98 legacy classes) will be "moved" via their copy operations. ... Furthermore, move operations won’t be generated for any class that explicitly declares a copy operation.

如果我显式删除move构造函数,则下面的代码会出错,但是如果我不删除对象"s1",则可以正确地构造副本,而不会出现任何错误.这是指向相同代码的wandbox链接: wandbox链接.我想我不了解删除move构造函数与不定义一个构造函数之间的区别.

The code below errors out if I explicitly delete the move constructor but if I don't the object "s1" gets copy constructed without any errors. Here's a wandbox link to the same code: wandbox link. I guess I'm not understanding the difference between deleting the move constructor and not defining one.

#include <iostream>

struct S
{
    S() = default;
    S(const S&) {
        std::cout << "Copying" << std::endl;
    }
   // S(S&&) = delete;
};

S return_lvalue() {
    S ret{};
    return ret;
}

int main() {
    std::cout << "Hello world" << std::endl;
    // Error here if I delete move constructor
    S s1 = return_lvalue();
}

推荐答案

我想我不了解删除move构造函数和不定义一个构造函数之间的区别.

I guess I'm not understanding the difference between deleting the move constructor and not defining one.

完成时

struct S
{
    S() = default;
    S(const S&) {
        std::cout << "Copying" << std::endl;
    }
};

编译器将不会生成move构造函数.如果尝试移动它,则重载分辨率将仅找到S(const S&),并且您将获得一个副本.使用

The compiler will not generate a move constructor. If you try to move it, overload resolution will only find S(const S&) and you'll get a copy. With

struct S
{
    S() = default;
    S(const S&) {
        std::cout << "Copying" << std::endl;
    }
    S(S&&) = delete;
};

当移动类型为S的对象时,重载分辨率会找到S(const S&)S(S&&),但会选择S(S&&),因为这是更好的匹配.然后看到它已被删除,并且出现错误.

When you move an object of type S, overload resolution finds S(const S&) and S(S&&) but it picks S(S&&) since it is the better match. Then it sees that it is deleted and you get an error.

您需要记住的是删除的构造函数,请不要将其从类中删除.它声明它们并使它们可用于重载解决方案,并且只有在发生重载解决方案之后,它才会检查是否将其删除.

The thing you need to remember is deleted constructors don't remove them from the class. It declares them and makes them available for overload resolution and it is only after overload resolution happens, that it checks if it is deleted.

这篇关于从右值中删除move构造函数并构造对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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