首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >复制赋值操作符隐式删除,因为字段中有一个已删除的复制赋值运算符。

复制赋值操作符隐式删除,因为字段中有一个已删除的复制赋值运算符。
EN

Stack Overflow用户
提问于 2021-09-15 23:39:37
回答 2查看 2K关注 0票数 1

一旦定义了析构函数,我就会得到这个错误,但是如果没有这个错误,编译就会成功,但是我非常想定义析构函数来调试一些seg错误。

代码语言:javascript
复制
class Socket {
    private:
        seastar::output_stream<char> socket;

    public:
        std::string peer;
    public:
        Socket() = default;

        template <typename... Args>
        explicit Socket(seastar::output_stream<char> &&s, std::string p) : socket(std::move(s)), peer(p) {}

        ~Socket() {
            std::cout << "Socket has gone out of scope" << "\n";
        }

        seastar::future<> send(std::string message) {
            co_await socket.write(message);
            co_await socket.flush();
        }

        seastar::future<> close() {
            co_await socket.close();
        }
};

编译失败,

代码语言:javascript
复制
error: object of type 'Socket' cannot be assigned because its copy assignment operator is implicitly deleted
        connection->second.socketObj = std::move(socketObj);
                                  ^
./socketwrapper.h:44:46: note: copy assignment operator of 'Socket' is implicitly deleted because field 'socket' has a deleted copy assignment operator
                seastar::output_stream<char> socket;

有办法解决这个问题吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-09-15 23:58:06

添加

代码语言:javascript
复制
Socket(Socket&&)=default;
Socket& operator=(Socket&&)=default;
票数 3
EN

Stack Overflow用户

发布于 2021-09-16 00:00:15

这里的基本问题是“为什么编译器在显式使用std::move()时尝试使用副本分配?”

让我们来看看一个简单的,格式良好的例子:

代码语言:javascript
复制
struct MyStruct {
  MyStruct() 
    : some_data(new int(12)) {}

  MyStruct(const MyStruct& other) 
    : some_data(new int(*other.some_data)) {}

  MyStruct& operator=(const MyStruct& rhs) {
    delete some_data;
    some_data = new int(*rhs.some_data);
    return *this;
  }

  ~MyStruct() { 
    delete some_data;
  }

  int * some_data;
};

MyStruct foo() {
  return MyStruct();
}

int main() {
  MyStruct a;
  a = foo(); // <--- copy-assignment here, no choice.
}

很明显,使用复制分配是很重要的,尽管它是一个RValue场景。

但是为什么这个程序一开始就有良好的形式呢?这是一个移动分配设置,我没有移动分配操作符。编译器就不能打我一巴掌吗?问题是,这是在C++11和移动语义之前形成的,所以它必须保持正确的行为。

因此,在任何其他构造函数/析构函数/赋值操作符存在的情况下,如果没有移动赋值/构造函数,则必须使用复制赋值/复制构造函数来代替,以防它恰好是很久以前编写的代码。

当前的解决方法是添加一个移动赋值操作符。在这一点上,它也可能有助于清理和完成全部规则-5。

代码语言:javascript
复制
class Socket {
    private:
        seastar::output_stream<char> socket;

    public:
        std::string peer;
    public:
        Socket() = default;

        explicit Socket(seastar::output_stream<char> &&s, std::string p) 
          : socket(std::move(s)), peer(p) {}
         
        Socket(Socket&&) = default;
        Socket& operator=(Socket&&) = default;

        // These are technically redundant, but a reader wouldn't know it,
        // so it's nice to be explicit.
        Socket(const Socket&) = delete;
        Socket& operator=(const Socket&) = delete;

// ...
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69200846

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档