了解共享指针的问题(生命周期,作为参数传递)

2024-04-22

我尝试从 boost asio 聊天示例开始并派生出一个自己的网络程序。不幸的是,我在理解到底发生了什么方面遇到了一些问题。我试图将我的程序减少到绝对最低限度。服务器类等待传入连接并创建会话对象来处理连接。这是服务器的代码:

#include <cstdint>
#include <iostream>
#include <sstream>
#include <memory>
#include <vector>

#include <boost/asio.hpp>
#include <boost/bind.hpp>

class Session : public std::enable_shared_from_this<Session>
{
public:
    Session(boost::asio::ip::tcp::socket __oSocket);
    virtual ~Session();
    void StartSession();
private:
    void StartRecv();
    std::vector<int32_t> m_vecSetupReceiveBuffer;
    boost::asio::ip::tcp::socket m_oSocket;
};

Session::Session(boost::asio::ip::tcp::socket __oSocket) :
    m_vecSetupReceiveBuffer({2}),
    m_oSocket(std::move(__oSocket))
{    }

Session::~Session()
{
    std::cout << "Deleted session" << std::endl;
}

void Session::StartSession()
{
    auto self(shared_from_this());
    std::cout << "StartSession()" << std::endl;
    boost::asio::async_write(m_oSocket, boost::asio::buffer(m_vecSetupReceiveBuffer),
    [this, self](boost::system::error_code _oError, std::size_t)
    {
        std::cout << m_vecSetupReceiveBuffer.size() << std::endl;
        StartRecv();
    });
}

void Session::StartRecv()
{
    auto self(shared_from_this());
    std::cout << "StartRecv()" << std::endl;
    boost::asio::async_read(m_oSocket, boost::asio::buffer(m_vecSetupReceiveBuffer),
    [this, self](boost::system::error_code _oError, std::size_t)
    {});
}

class Server
{
public:
    Server(boost::asio::io_service& _rIOService, uint32_t _nPort);
    virtual ~Server();
private:
    void StartAccept();
    boost::asio::ip::tcp::acceptor m_oAcceptor;
    boost::asio::ip::tcp::socket m_oSocket;
};

Server::Server(boost::asio::io_service& _rIOService, uint32_t _nPort) :
    m_oAcceptor(_rIOService, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), _nPort)),
    m_oSocket(_rIOService)
{
    StartAccept();
}

Server::~Server()
{}

void Server::StartAccept()
{
    m_oAcceptor.async_accept(m_oSocket,
    [this](boost::system::error_code _oError)
    {
        std::make_shared<Session>(std::move(m_oSocket))->StartSession();
        StartAccept();
    });
}


int main(int argc, char* argv[])
{
    boost::asio::io_service _oIOServerService;
    std::shared_ptr<Server> _pServer(std::make_shared<Server>(_oIOServerService, 2000));
    _oIOServerService.run();
    return 0;
}

这段代码按预期运行,但是当我尝试调整一些东西并进行一些操作时,我发现我不明白共享指针何时真正创建和删除以及它们存储在哪里。例如我试图改变std::make_shared<Session>(std::move(m_oSocket))->StartSession(); to std::make_shared<Session>(std::move(m_oSocket));并添加了StartSession();在 Session 类的构造函数中。如果我运行代码,它会抛出

terminate called after throwing an instance of 'std::bad_weak_ptr'
what():  bad_weak_ptr
Aborted (core dumped)

这大概发生在auto self(shared_from_this());。但我不明白为什么?我应该在我的代码中更改什么?所以我认为我的问题是我不明白如何正确使用shared_ptr,如何在这些构造中使用它,我可以在哪里访问它以及如何使其可访问。此外,尚不清楚为什么我有时必须使用this以及何时使用shared_from_this()。有没有好的教程或简单的经验法则?

我也不清楚为什么有些人使用 lambda 函数表示法,而有些人则使用boost::bind记法和有什么区别?

所以请原谅我的新手问题,我试图在教程中找到一些信息,但我只是对这些共享指针和 boost::asio 感到困惑。似乎总是做一些奇怪的事情。


You get std::bad_weak_ptr因为没有shared_ptr owning this在你的建设过程中Session。你还在身体里make_shared,并且它还没有完成创建shared_ptr.

shared_from_this()只能从以下实例获得Session,它是一个成员函数。你通过派生继承了它std::enable_shared_from_this.

lambda 是用以下副本构造的self,以及成员Session就好像可用this还指出Session对象,而不是 lambda 对象,因为this capture

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

了解共享指针的问题(生命周期,作为参数传递) 的相关文章

  • C++11 / VS2010:返回不可复制但可移动对象的容器

    考虑以下代码 include
  • Eigen::aligned_allocator 因 std::unordered_multimap 失败

    我正在尝试在 XCode 6 中编译此代码 std unordered multimap lt Frame Sim3 std hash
  • 对于所有对象类型 T 来说,sizeof(T) >=alignof(T) 总是这样吗?

    对于任何对象类型T是不是总是这样sizeof T 至少与alignof T 直观上似乎是这样 因为即使您调整对象的对齐方式 例如 struct small char c 高于通常的情况 它们的 大小 也会向上调整 以便数组中的对象之间的关系
  • 为什么大多数平台上没有“aligned_realloc”?

    MSVC有自己的非标准函数 aligned malloc aligned realloc and aligned free C 17和C11引入了 std aligned alloc 其结果可以是de分配有free or realloc B
  • 分配器感知容器和propagate_on_container_swap

    The std allocator traits模板定义了一些常量 例如propagate on container copy move assign让其他容器知道它们是否应该在复制或移动操作期间复制第二个容器的分配器 我们还有propag
  • 引用重载,与单独的值传递 + std::move 相比?

    似乎有关 C 0x 右值的主要建议是向类中添加移动构造函数和移动运算符 直到编译器默认实现它们 但如果您使用 VC10 等待是一种失败的策略 因为自动生成可能要到 VC10 SP1 才会出现 或者在最坏的情况下 直到 VC11 等待这一切的
  • 在编译时使用 Constexpr 填充数组

    我想使用 constexpr 填充枚举数组 数组的内容遵循一定的模式 我有一个枚举 将 ASCII 字符集分为四类 enum Type Alphabet Number Symbol Other constexpr Type table 12
  • C++0x 可变参数模板按引用传递

    我想为我的应用程序使用可变参数模板功能 但我不希望对象按值传递 因为在我的情况下对象非常复杂 我想通过引用传递它们 而不是作为指针 void func template
  • 何时使用 =default 使析构函数默认?

    尽管对构造函数使用 default 对我来说很清楚 即强制编译器在其他构造函数存在时创建默认构造函数 但我仍然无法理解这两种类型的析构函数之间的区别 那些使用 default 的 那些没有显式定义并由编译器自动生成的 我唯一想到的是 gro
  • C++0x中disable_if在哪里?

    Boost 两者都有enable if and disable if 但 C 0x 似乎缺少后者 为什么它被排除在外 C 0x 中是否有元编程工具允许我构建disable if按照enable if 哦 我刚刚注意到std enable i
  • 具有多个谓词的 C++11 算法

    功能如std find if来自algorithmheader 确实很有用 但对我来说 一个严重的限制是我只能为每次调用使用 1 个谓词count if 例如给定一个像这样的容器std vector我想同时应用相同的迭代find if 多个
  • make_shared<>() 中的 WKWYL 优化是否会给某些多线程应用程序带来惩罚?

    前几天我偶然看到这个非常有趣的演示 http channel9 msdn com Events GoingNative GoingNative 2012 STL11 Magic Secrets作者 Stephan T Lavavej 其中提
  • 为什么 std::function 不是有效的模板参数,而函数指针却是?

    我已经定义了名为的类模板CallBackAtInit其唯一目的是在初始化时调用函数 构造函数 该函数在模板参数中指定 问题是模板不接受std function作为参数 但它们接受函数指针 为什么 这是我的代码 include
  • 如何在 GCC 5 中处理双 ABI?

    我尝试了解如何克服 GCC 5 中引入的双重 ABI 的问题 但是 我没能做到 这是一个重现错误的非常简单的示例 我使用的GCC版本是5 2 如您所见 我的主要函数 在 main cpp 文件中 非常简单 main cpp include
  • 过滤参数包的类型

    我想知道是否可以过滤传递给可变参数模板 基于谓词模板 的类型以生成另一个包含满足谓词的类型的可变参数模板 Filter a parameter pack template
  • const、span 和迭代器的问题

    我尝试编写一个按索引迭代容器的迭代器 AIt and a const It两者都允许更改容器的内容 AConst it and a const Const it两者都禁止更改容器的内容 之后 我尝试写一个span
  • 如何构建支持 C++0x 的 Boost?

    我不知道如何使用 C 0x 编译器构建 Boost 必须给 bjam 提供哪个选项 应该修改 user config 文件吗 有人可以帮助我吗 最好的 维森特 我已经找到答案了 我正在等待类似 std 的功能 并将其命名如下 bjam st
  • remove_reference 如何禁用模板参数推导?

    根据这个链接 https stackoverflow com questions 7779900 why is template argument deduction disabled with stdforward 不允许模板参数推导st
  • Linux 上哪个版本的 C++ 库符合“ISO C++ 11”标准?

    目前我的计算机上有 Debian Squeeze AMD64 linux libstdc 5 和 libstdc 6 这些 C 库符合 ISO 标准 C 11 吗 不 它们并不完全符合 但它们有一些元素 stdlibc 上的 C 11 支持
  • 元组在 VS2012 中如何工作?

    Visual Studio 2012 功能 tuples但不是可变参数模板 这是如何完成的 如何在不使用可变模板的情况下实现元组 简而言之 微软做了与之前在 NET 中实现类似元组的数据类型完全相同的事情 创建许多版本 每个版本都有固定数量

随机推荐