【问题标题】:Overloading operator new for other class为其他类重载运算符 new
【发布时间】:2020-10-13 20:50:53
【问题描述】:

用例

我有一个Node 类,它读取、创建Message 对象并将其发送到其他Node 类。我不想修改 Message 类的构造函数,因为我也在其他类中使用它。

Message 对象基本上是这样的(Message.hpp 文件)

类消息{
    size_t 大小;
    字符*缓冲区;

    消息(size_t 容量):缓冲区(新字符 [容量]),大小(0){}
}

用例可能如下所示(.cpp 文件)

Node::Node() : header_size(sizeof(int)) {}

Node::processMessage(const unique_ptr& message){
    向量& 事件 = 读取事件(消息); // 读取 char* 缓冲区
    const int message_id = readMID(message); // 读取缓冲区的另一部分
    矢量> messagesToSend;

    
    对于(常量事件和事件:事件){
        unique_ptr message(new Message(header_size + sizeof(Event));
        writeInMessage(消息,事件);
        writeInMessage(message, message_id);
        messagesToSend.push_back(std::move(message));
    }

    发送消息(消息发送);
}

前面的这个用例只是将消息中包含的事件分片到许多不同的消息中,并保持相同的消息 id。

在我的用例中,消息头通常是一个用于标识消息的整数,而缓冲区的其余部分则填充了一系列可能属于不同类型的事件。现在,我想修改Node,让它自动管理标识符,以便用户可以专注于事件处理,我想知道是否可以重载或替换operator new,以添加header_sizeNode 类中创建新消息对象时分配的内存大小。

重载应该允许我写这样的东西(.cpp)

Node::processMessage(const unique_ptr& message){
    向量& 事件 = 读取事件(消息);
    矢量> messagesToSend;

    
    对于(常量事件和事件:事件){
        unique_ptr message(new Message(sizeof(Event));
        writeInMessage(消息,事件);
        messagesToSend.push_back(std::move(message));
    }

    发送消息(消息发送);
}

标题的管理将通过processMessage()之前或之后调用的其他方法来完成。

我已经看过了

我已经阅读了一些 stackoverflow 问题和一些关于如何替换 operator new 的文档,但它始终在全局或当前类中使用(在我的情况下,我不希望替换 @987654332 中的运算符@ 类,但在 Node 类中)。

我依稀记得有一个关于运算符重载和新/删除运算符重载的 stackoverflow 常见问题解答,不建议在此处修改这些运算符:What are the basic rules and idioms for operator overloading?

问题

为此,在 Node 类中重载操作符 new 是一个好主意还是至少是一个合法的主意?如果没有,正确的做法是什么?

如果这种方法是合法的,它会是什么样子? Message 类是否需要将运算符重载定义为友元方法或类似方法?另外,我还需要重载operator delete 吗?

【问题讨论】:

  • 那么为缓冲区分配更多内存的唯一方法是通过Message类的构造函数?我不想修改Message 类。我不能增加原始内存量并在缓冲区中写入超过 sizeof(Event) 个字节吗?这会导致内存泄漏吗?
  • Node 创建Message 时,您是否要为sizeof(int) 分配额外的字节?
  • 如果没有其他选择,我将保持代码原样 - 使用new Message(header_size + sizeof(Event))。但是,如果有一种方法可以编写 new Message(sizeof(Event)) 而不触及 Message 构造函数并保留相同数量的内存,那么我会接受它。也许operator new 不是办法。
  • 我刚看到你的回答。是的,我希望分配sizeof(int) 更多的字节,而不必每次都写。但仅限于Node 类的代码中。
  • 重载operator new只有两个选项。您可以重载全局operator new 或成员operator new。全局operator new 将影响当前翻译单元中new 的所有使用,因此我们可以忽略它。在这里用处不大。另一个选项是将特定类的operator new 重载为成员运算符。但是,这只改变了分配 that 类的方式。如果您超载Node::operator new,那么您只会更改执行new Node 时发生的情况。您不能在 Node 中更改 Message::operator new

标签: c++ operator-overloading new-operator delete-operator


【解决方案1】:

感谢François Andrieux 的及时答复。我的问题的简短回答是创建一个工厂模式来创建 Message 对象。类似的东西:

(节点.cpp)

unique_ptr Node::createMessage(size_t capacity) {
    return unique_ptr(new Message(capacity + header_size));
}

这样,用户不必在每次想要创建新的消息对象时精确地确定标头大小。这样做的缺点是用户必须知道要使用的确切方法。如果Message 自然构造函数不可访问,则可以强制用户使用此方法。

重载operator new 不是答案,理由如下:

重载operator new 只有两个选项。您可以重载全局operator new 或成员operator new。全局 operator new 将影响当前翻译单元中所有 new 的使用,因此我们可以忽略它。在这里用处不大。另一个选项是将特定类的operator new 重载为成员运算符。但是,这只改变了分配该类的方式。如果您超载Node::operator new,那么您只会更改执行new Node 时发生的情况。您不能在 Node 中更改 Message::operator new

另一种分配比自然构造函数更多空间的可能性是使用placement new。然而,这使得构造和破坏过于复杂,这不是这里的预期目标。另外,让用户每次都写new Message(header_size + capacity)比让他分配和释放内存的风险要小。

【讨论】:

    猜你喜欢
    • 2011-07-21
    • 1970-01-01
    • 2017-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多