当前位置: 首页 > 知识库问答 >
问题:

C“有效现代C”中的默认移动操作

阮华美
2023-03-14

第17项:了解特殊成员函数的生成。

>

  • 移动操作仅为未显式声明的类移动操作、复制操作或析构函数生成。

    现在,当我提到移动操作move-construction
    或move-assigning一个数据成员或基类时,
    并不能保证实际会发生移动
    “Memberwise移动”实际上更像Memberwise
    移动请求,因为类型没有启用移动(…)
    将通过其复制操作“移动”。

    但是,我无法在我的环境中验证它们。

    // compiled
    #include <iostream>
    using namespace std;
    class Base {
    public:
        ~Base() {}
    };
    int main() {
        Base a, c;
        Base b(move(a));
        c = move(b);
        // explicitly destructor does not disable 
        // default move constuctor and move assignment operator
        return 0;
    }
    
    class Base {
    public:
        Base() {}
        Base(Base& b) {}
        ~Base() {}
    };
    class Num {
    private:
        Base b;
    };
    int main() {
        Num a, c;
        c = move(a); // passed
        Num b(move(c)); // error
        // explicitly Base::Base(Base& b) disable default move 
        // move conctructor. 
        // Num's default move constructor can not find any move
        // constructor for member object Base b, which lead to an 
        // error. Num's default move constructor does not "moved" 
        // Base b via their copy operations which is declared.
        return 0;
    }
    

    第一个断言可能因环境而异,但第二个断言几乎是错误的<我对此很困惑。请帮帮我。

  • 共有1个答案

    宁鹏程
    2023-03-14
    class Base {
    public:
        ~Base() {}
    };
    

    因为Base具有用户声明的析构函数,所以它根本没有移动构造函数或移动赋值操作符。那些线条

    Base b(move(a));
    c = move(b);
    

    实际上,分别调用复制构造函数和复制赋值运算符。

    class Base {
    public:
        Base() {}
        Base(Base& b) {}
        ~Base() {}
    };
    class Num {
    private:
        Base b;
    };
    

    同样,Base没有移动构造函数。但是,Num确实有一个隐式声明的移动构造函数,因为Num本身不声明任何特殊的成员函数。然而,它被隐含地定义为删除,因为默认定义将是格式错误的:

    Num::Num(Num&& n) : b(std::move(n.b)) {}
    // Cannot convert rvalue of type `Base` to `Base&`
    // for the copy constructor to be called.
    

    请注意,b的“移动”确实尝试使用复制构造函数,但它不能。

     类似资料:
    • 本文向大家介绍C#属性的默认值,包括了C#属性的默认值的使用技巧和注意事项,需要的朋友参考一下 示例 可以使用初始化程序(C#6)设置默认值 如果它是只读的,则可以返回如下值:            

    • 在 C++中,定义函数时可以给形参指定一个默认的值,这样调用函数时如果没有给这个形参赋值(没有对应的实参),那么就使用这个默认的值。也就是说,调用函数时可以省略有默认值的参数。如果用户指定了参数的值,那么就使用用户指定的值,否则使用参数的默认值。 所谓默认参数,指的是当函数调用中省略了实参时自动使用的一个值,这个值就是给形参指定的默认值。下面是一个简单的示例: 运行结果: 10, 3.5, # 2

    • 本文向大家介绍C#默认等于行为。,包括了C#默认等于行为。的使用技巧和注意事项,需要的朋友参考一下 示例 Equals在Object类本身中声明。 默认情况下,Equals具有以下行为: 如果实例是引用类型,则Equals仅当引用相同时才返回true。 如果实例是值类型,则Equals仅当类型和值相同时才返回true。 string是一个特例。它的行为类似于值类型。            

    • 我遵循本指南https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-8.0/default-interface-methods使用默认接口实现功能。我复制了一段在接口中定义默认实现的代码,然后在接口中重写它: 但它给出了一个错误和一个警告。设置为,为。为什么即使在官方文件中有描述也不起作用

    • 我的api如下所示: 对于查询,我们只想允许查询枚举中列出的某些属性,如下所示: 我加了 在启动阶段。cs,但这不适用于默认值,我得到以下生成的虚张声势,默认值为0而不是字符串: 如何使默认值显示为字符串?

    • 本文向大家介绍C#代码实现PDF文档操作类,包括了C#代码实现PDF文档操作类的使用技巧和注意事项,需要的朋友参考一下 本文纯干货,贴上PDF文档操作类C#代码,需要添加iTextSharp.dll引用才可以正常通过编译。 废话不多说了,直接给大家贴代码了。 代码如下: 呐喊教程友情提醒需要注意点:需要添加iTextSharp.dll引用才可以正常通过编译。