美文网首页C/C++
移动构造函数常见错误(一)

移动构造函数常见错误(一)

作者: 门口的野蛮人 | 来源:发表于2021-12-19 04:59 被阅读0次

这两天在自己复现那本中文翻译出了名的烂的C++高并发编程实践里的线程池那一章节的代码,偶然发现了一个关于移动构造函数的问题,还别说,要是不注意,还是挺容易犯这个错误的
举个例子:

#include <string>
#include <iostream>
#include <iomanip>
#include <utility>

class A {
private:
    int a;
public:
    A() {}
    A(int a_value){a = a_value;}
    int get_value() {return a;}
    ~A(){}
    A(A&& a_) {a = std::move(a_.a);}
    A& operator = (A &&a_)
    {
        a = std::move(a_.a);
        return *this;
    }
};

void f(A &a1, A &a2)
{
    a2 = std::move(a1);
}

int main()
{
    A a1(2);
    std::cout << a1.get_value() << std::endl;
    A a2;
    f(a1, a2);
    std::cout << a2.get_value() << std::endl;

    return 0;
}

这时如果你编译该代码,会发现以下的问题:

main.cpp:34:22: error: use of deleted function ‘constexpr A& A::operator=(const A&)’
a1 = std::move(a2);

如果你写成这样则没有问题:

#include <string>
#include <iostream>
#include <iomanip>
#include <utility>

class A {
private:
    int a;
public:
    A() {}
    A(int a_value){a = a_value;}
    int get_value() {return a;}
    ~A(){}
    A(A&& a_) {a = std::move(a_.a);}
};

int main()
{
    A a1(2);
    std::cout << a1.get_value() << std::endl;
    A a2 = std::move(a1);
    std::cout << a2.get_value() << std::endl;
    return 0;
}

看出问题在哪里了吗,问题就在第一种情况使用了a2的传参引用,也就是说这时候a2已经在内存里完成了构造,而第二种情况的a2则是直接利用A的移动构造函数来实现构造
这也就解释了第一种情况无法通过编译的原因,因为实际上第一种情况里,因为自定义了移动构造函数,则默认的移动构造函数和移动等号运算符被删除,用户必须自定义一个移动等号运算符重载才能通过编译,如下:

#include <string>
#include <iostream>
#include <iomanip>
#include <utility>

class A {
private:
    int a;
public:
    A() {}
    A(int a_value){a = a_value;}
    int get_value() {return a;}
    ~A(){}
    A(A&& a_) {a = std::move(a_.a);}
    A& operator = (A &&a_)
    {
        a = std::move(a_.a);
        return *this;
    }
};

void f(A &a1, A &a2)
{
    a2 = std::move(a1);
}

int main()
{
    A a1(2);
    std::cout << a1.get_value() << std::endl;
    A a2;
    f(a1, a2);
    std::cout << a2.get_value() << std::endl;

    return 0;
}

当然这种情况下你可以只定义移动赋值运算符,不过我个人还是建议如果不使用默认的移动构造函数,则最好同时定义好移动构造函数和移动复制运算符

相关文章

  • 移动构造函数常见错误(一)

    这两天在自己复现那本中文翻译出了名的烂的C++高并发编程实践里的线程池那一章节的代码,偶然发现了一个关于移动构造函...

  • c++11 拷贝控制

    拷贝控制操作包括,拷贝构造函数,拷贝赋值运算符,移动构造函数,移动赋值运算符,析构函数。拷贝和移动构造函数定义了用...

  • 18/3

    1.特殊成员函数(6个):默认构造函数、复制构造函数、复制赋值运算符和析构函数、移动构造函数、移动赋值运算符 这些...

  • C++中为什么move construct需要加noexcept

    C++ 11中增加了名为移动构造函数的构造函数类型。通过使用移动构造函数,我们可以在进行对象复制时直接“窃取”拷贝...

  • 2023-01-18 C++实现string类

    实现string类,用于学习 拷贝构造函数/拷贝赋值运算符/移动构造函数/移动赋值运算符

  • 移动构造函数

    暂存一下。 =====================

  • 移动构造函数

    #include #include #include #include #include #in...

  • JavaScript原型链

    常见概念 构造函数 构造函数-扩展 原型规则和示例 原型链 instanceof 构造函数 任何一个函数都可以被n...

  • 十八、Swift3.0之便利构造函数

    遍历构造函数在类别中使用比较常见,如在UIColor+Extension实现一个简单的遍历构造函数: 遍历构造函数...

  • C++11六大函数(构造函数,移动构造函数,移动赋值操作符,复制

    在C++中,有三大函数复制控制(复制构造函数,赋值操作符,析构函数),而在C++11中,加入了移动构造函数,移动赋...

网友评论

    本文标题:移动构造函数常见错误(一)

    本文链接:https://www.haomeiwen.com/subject/nxvnfrtx.html