为其他 class 重载运算符 new

Overloading operator new for other class

用例

我有一个 Node class 可以读取、创建 Message object 并将其发送给其他 Node class。我不想修改 Message class 构造函数,因为我也在其他 class 中使用它。

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

class Message {
    size_t size;
    char* buffer;

    Message(size_t capacity) : buffer(new char[capacity]), size(0) {}
}

一个用例可能看起来像那样(.cpp 文件)

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

Node::processMessage(const unique_ptr<Message>& message){
    vector<Event>& events = readEvents(message); // reads the char* buffer
    const int message_id = readMID(message); // reads another part of the buffer
    vector<unique_ptr<Message>> messagesToSend;

    
    for (const Event& event : events){
        unique_ptr<Message> message(new Message(header_size + sizeof(Event));
        writeInMessage<Event>(message, event);
        writeInMessage<int>(message, message_id);
        messagesToSend.push_back(std::move(message));
    }

    sendMessages(messagesToSend);
}

这个先前的用例只是将一条消息中包含的事件分成许多不同的消息,并保持相同的消息 ID。

在我的用例中,消息 header 通常是一个整数,用于标识消息,缓冲区的其余部分填充了一系列可能属于不同类型的事件。现在,我想修改 Node 使其自动管理标识符,以便用户可以专注于事件处理,我想知道是否可以重载或替换 operator new 用于特定目的在 Node class.

中创建新消息 object 时,将 header_size 添加到已分配内存的大小

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

Node::processMessage(const unique_ptr<Message>& message){
    vector<Event>& events = readEvents(message);
    vector<unique_ptr<Message>> messagesToSend;

    
    for (const Event& event : events){
        unique_ptr<Message> message(new Message(sizeof(Event));
        writeInMessage<Event>(message, event);
        messagesToSend.push_back(std::move(message));
    }

    sendMessages(messagesToSend);
}

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

我已经看过了

我已经阅读了一些 Whosebug 问题和一些关于如何替换 operator new 的文档,但它总是全局使用或用于当前 class(在我的情况下我不希望替换Message class 但在 Node class).

中的运算符

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

问题

为此,在 Node class 中重载 operator new 是个好主意还是至少是合法的?如果不是,正确的方法是什么?

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

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

(Node.cpp)

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

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

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

There are only two options for overloading operator new. You can overload the global operator new or the member operator new. The global operator new will impact all uses of new in the current translation unit, so we can ignore that one. It won't be useful here. The other option is overloading operator new for a specific class as a member operator. However, that only changes how allocating that class is done. If you overload Node::operator new then you only change what happens when you do new Node. You can't change Message::operator new from within Node

另一种分配比自然构造函数更多 space 的可能性是使用 placement new。然而,这使得构建和破坏 over-complicated 这不是预期的 objective 。此外,让用户每次都写入 new Message(header_size + capacity) 比让他分配和释放内存的风险更小。