c++ - 将对未初始化对象的引用传递给父类(super class)构造函数,然后用它的移动构造函数初始化所述对象?

标签 c++ oop boost

我正在编写一个 C++ websocket 服务器库。在我提供的示例之一中,我使用了两个类 session_basesession .我这样做是为了获得 tcp::socket session_base 中的对象父类在将对它的引用传递给 ws::session<tcp::socket> 之前初始化(使用移动构造函数)存储此引用供以后使用的父类。我创建 ws:session 作为模板类的原因是我可以使用 boost::asio::ssl::stream s 以及 tcp 套接字。

tcp::socket 是否有效?反对 session 的成员类,将对此未初始化对象的引用传递给 ws::session构造函数(尚未使用 tcp::socket - 仅存储引用)然后初始化 tcp::socket对象之后使用套接字移动构造函数?

当前代码:

using boost::asio::ip::tcp;

class session_base {
public:
    session_base(tcp::socket socket) : socket_(std::move(socket)) { }
protected:
    tcp::socket socket_;
};

using T = tcp::socket;
class session : public session_base, public ws::session<T> {
public:
    session(tcp::socket socket) :
        session_base(std::move(socket)), ws::session<T>(socket_)
    {
        std::cout << "session()\n";
    }

    ~session() {
        std::cout << "~session()\n";
    }

private:
    void on_open() override {
        std::cout << "WebSocket connection open\n";
    }

    void on_msg(const ws::message &msg) override {
        /* Do stuff with msg */

        read();
    }

    void on_close() override {
        std::cout << "WebSocket connection closed\n";
    }

    void on_error() override {
        std::cout << "WebSocket connection error\n";
    }
};

建议代码:

下面建议的代码对我有用,但我想知道这是定义的行为并推荐。

using boost::asio::ip::tcp;

using T = tcp::socket;
class session : public ws::session<T> {
public:
    session(tcp::socket socket) :
        ws::session<T>(socket_), socket_(std::move(socket))
    {
        std::cout << "session()\n";
    }

    ~session() {
        std::cout << "~session()\n";
    }

private:
    tcp::socket socket_;

    void on_open() override {
        std::cout << "WebSocket connection open\n";
    }

    void on_msg(const ws::message &msg) override {
        /* Do stuff with msg */

        read();
    }

    void on_close() override {
        std::cout << "WebSocket connection closed\n";
    }

    void on_error() override {
        std::cout << "WebSocket connection error\n";
    }
};

完整来源:https://github.com/alexyoung91/ws

最佳答案

如果 ws::session 构造函数仅存储对套接字的引用但不使用该引用来调用套接字成员函数或访问数据成员,则程序是良构的.该标准将此称为对 3.8/6 ([basic.life/6]) 中分配存储的引用:

Similarly, before the lifetime of an object has started but after the storage which the object will occupy has been allocated or, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, any glvalue that refers to the original object may be used but only in limited ways. For an object under construction or destruction, see 12.7. Otherwise, such a glvalue refers to allocated storage (3.7.4.2), and using the properties of the glvalue that do not depend on its value is well-defined. The program has undefined behavior if:

— an lvalue-to-rvalue conversion (4.1) is applied to such a glvalue,

— the glvalue is used to access a non-static data member or call a non-static member function of the object, or

— the glvalue is implicitly converted (4.10) to a reference to a base class type, or

— the glvalue is used as the operand of a static_cast (5.2.9) except when the conversion is ultimately to cv char& or cv unsigned char&, or

— the glvalue is used as the operand of a dynamic_cast (5.2.7) or as the operand of typeid.

请注意,必须在获取引用时分配存储,调用session构造函数时也是如此。

但尽管如此,我还是不推荐这种方法。主要是因为在 ws::session 构造函数中很容易忘记传递的引用引用了一个尚未初始化的对象,并在以后引入错误。最好使用 base-from-member idiom并保留您的原始代码。

关于c++ - 将对未初始化对象的引用传递给父类(super class)构造函数,然后用它的移动构造函数初始化所述对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34477383/

相关文章:

c++ - 如何避免使用插入迭代器调用复制构造函数

c# - 关于封装的概念

c# - 如何检查方法是否返回 true

c++ - 使用 C++ boost::split 拆分字符串而不拆分引用文本

C++ : Memory overhead due to virtuality?

c++ - Visual Studio Code 以类似 NetBeans 的方式远程调试 c++

c++ - 在 C++ 中使用 fscanf 读取带有 int 和 float 的选项卡式文件

c++ - 从现代 C++ 中的命令类型中查找命令处理程序

c++ - 使用 boost::pool_allocator 时不调用 move 构造函数

c++ - 通过动态链接和手动设置 boost 单元测试框架