error: call to implicitly-deleted copy constructor of 编译报错分析

在某次编译过程中,出现此报错,根据报错日志分析,查明原因,觉得很有意思,于是决定分享出来。

首先,先看例子代码(在main函数中关注test3对象的赋值操作即可,test1和test2对象后面会叙述)

// Example program
#include <iostream>
#include <string>

class NoCopyConstructor {
public:
    NoCopyConstructor(){};
    ~NoCopyConstructor(){};
    NoCopyConstructor(const NoCopyConstructor &) = delete;  // 拷贝构造函数不可用
    // NoCopyConstructor& operator=(const NoCopyConstructor &)  = delete; // "="运算符不可用
};

class Test {
public:
    Test(){};
    ~Test(){};
public:
    int a;
    int b;
    NoCopyConstructor noCopyConstructor;
};

Test getTest(int a, int b) {
    Test test;
    test.a = a;
    test.b = b;
    return test;
}

int main()
{
  Test test1;
  test1.a = 1;
  test1.b = 2;
  
  Test test2;
  test2 = test1;
  std::cout << " test2 a = " << test2.a << ", test2 b = "<< test2.b <<"!\n";
  
  Test test3;
  test3 = getTest(3, 4);
  std::cout << " test3 a = " << test3.a << ", test3 b = "<< test3.b <<"!\n";
}

接着是编译报错日志

main.cpp:27:12: error: call to implicitly-deleted copy constructor of 'Test'
    return test;
           ^~~~
main.cpp:20:23: note: copy constructor of 'Test' is implicitly deleted because field 'noCopyConstructor' has a deleted copy constructor
    NoCopyConstructor noCopyConstructor;
                      ^
main.cpp:9:5: note: 'NoCopyConstructor' has been explicitly marked deleted here
    NoCopyConstructor(const NoCopyConstructor &) = delete;  // 拷贝构造函数不可用
    ^
1 error generated.

可以看到编译报错的原因是因为在test作为返回值时调用了Test类的默认拷贝构造函数,在拷贝过程中调用了Test类成员对象NoCopyConstructor的拷贝构造函数,但是NoCopyConstructor的拷贝构造函数已经设置为delete,即不可使用,就会出现这个编译报错,切记这个报错和析构函数没有关系。

在实际应用中,通常我们引用的so库对象中,有些类因为某些原因禁止使用拷贝构造函数,我们无法修改so库中的拷贝构造函数的属性,但是可以通过自定义我们当前类的拷贝构造函数来规避问题

针对上面代码,由于NoCopyConstructor并没有被用来处理数据,这时可以修改代码

// Example program
#include <iostream>
#include <string>

class NoCopyConstructor {
public:
    NoCopyConstructor(){};
    ~NoCopyConstructor(){};
    NoCopyConstructor(const NoCopyConstructor &) = delete;  // 拷贝构造函数不可用
    // NoCopyConstructor& operator=(const NoCopyConstructor &)  = delete; // "="运算符不可用
};

class Test {
public:
    Test(){};
    /**
     * 重写拷贝构造函数,没有对NoCopyConstructor赋值
     */
    Test(const Test& test)
    {
        this->a = test.a;
        this->b = test.b;
    }
    ~Test(){};
public:
    int a;
    int b;
    NoCopyConstructor noCopyConstructor;
};

Test getTest(int a, int b) {
    Test test;
    test.a = a;
    test.b = b;
    return test;
}

int main()
{
  Test test1;
  test1.a = 1;
  test1.b = 2;
  
  Test test2;
  test2 = test1;
  std::cout << " test2 a = " << test2.a << ", test2 b = "<< test2.b <<"!\n";
  
  Test test3;
  test3 = getTest(3, 4);
  std::cout << " test3 a = " << test3.a << ", test3 b = "<< test3.b <<"!\n";
}

运行结果

 test2 a = 1, test2 b = 2!
 test3 a = 3, test3 b = 4!

建议关注知识点:默认拷贝构造函数、拷贝构造函数的概念、函数返回值、左值,其他就先不复述了。


再分析个类似编译报错“has a deleted copy assignment operator”

先看代码(这次关注test1和test2对象)

// Example program
#include <iostream>
#include <string>

class NoCopyConstructor {
public:
    NoCopyConstructor(){};
    ~NoCopyConstructor(){};
    // NoCopyConstructor(const NoCopyConstructor &) = delete;  // 拷贝构造函数不可用
    NoCopyConstructor& operator=(const NoCopyConstructor &)  = delete; // "="运算符不可用
};

class Test {
public:
    Test(){};
    Test(const Test& test)
    {
        this->a = test.a;
        this->b = test.b;
    }
    ~Test(){};
public:
    int a;
    int b;
    NoCopyConstructor noCopyConstructor;
};

Test getTest(int a, int b) {
    Test test;
    test.a = a;
    test.b = b;
    return test;
}

int main()
{
  Test test1;
  test1.a = 1;
  test1.b = 2;
  
  Test test2;
  test2 = test1;
  std::cout << " test2 a = " << test2.a << ", test2 b = "<< test2.b <<"!\n";
  
  Test test3;
  test3 = getTest(3, 4);
  std::cout << " test3 a = " << test3.a << ", test3 b = "<< test3.b <<"!\n";
}

编译报错如下

main.cpp:42:9: error: object of type 'Test' cannot be assigned because its copy assignment operator is implicitly deleted
  test2 = test1;
        ^
main.cpp:25:23: note: copy assignment operator of 'Test' is implicitly deleted because field 'noCopyConstructor' has a deleted copy assignment operator
    NoCopyConstructor noCopyConstructor;
                      ^
main.cpp:10:24: note: 'operator=' has been explicitly marked deleted here
    NoCopyConstructor& operator=(const NoCopyConstructor &)  = delete; // "="运算符不可用
                       ^
main.cpp:46:9: error: object of type 'Test' cannot be assigned because its copy assignment operator is implicitly deleted
  test3 = getTest(3, 4);
        ^
main.cpp:25:23: note: copy assignment operator of 'Test' is implicitly deleted because field 'noCopyConstructor' has a deleted copy assignment operator
    NoCopyConstructor noCopyConstructor;
                      ^
main.cpp:10:24: note: 'operator=' has been explicitly marked deleted here
    NoCopyConstructor& operator=(const NoCopyConstructor &)  = delete; // "="运算符不可用
                       ^
2 errors generated.

根据错误日志可以看出NoCopyConstructor的赋值运算符"="已经设置为delete,即不可使用, 同理解决这个问题,可以自定义我们当前类的赋值运算符"="来规避问题

部分代码如下

class Test {
public:
    Test(){};
    Test(const Test& test)
    {
        this->a = test.a;
        this->b = test.b;
    }
    /*
     * 重写“=”, 不对NoCopyConstructor赋值
     */
    Test& operator=(const Test &test)
    {
        this->a = test.a;
        this->b = test.b;
        return *this;
    }

    ~Test(){};
public:
    int a;
    int b;
    NoCopyConstructor noCopyConstructor;
};

最好的解决方案还是在调用Test类赋值过程中,采用指针方式传递,但是要注意指针浅拷贝过程指向的是同一段内存,很有可能在原对象析构时,释放了内存,导致新对象指针调用释放后的内存报错,这就是另一个需要研究的问题了。

写了一篇模棱两可的文章,可能会给大家带来更多困扰,希望能和大家一起讨论,共同进步,献丑了~~~

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值