3

假设以下代码:

class ChannelHandle;
class SessionHandle;

typedef ChannelHandle& ChannelHandleRef;
typedef SessionHandle& SessionHandleRef;

class RemoteChannelHandle
{
public:
    RemoteChannelHandle(
        ChannelHandleRef pChannelHandle, SessionHandleRef pSessionHandle);
    RemoteChannelHandle(RemoteChannelHandle&&);
    ~RemoteChannelHandle();

    void CloseChannel();

#ifndef _MSC_VER
    RemoteChannelHandle& operator=(RemoteChannelHandle&&) = delete;
    RemoteChannelHandle(RemoteChannelHandle const&) = delete;
    RemoteChannelHandle& operator=(RemoteChannelHandle const&) = delete;
#endif
private:
    LIBSSH2_CHANNEL* channel;
    ChannelHandleRef channelHandle;
    SessionHandleRef sessionHandle;
};

RemoteChannelHandle::RemoteChannelHandle(
    ChannelHandleRef pChannelHandle, SessionHandleRef pSessionHandle)
    : channel(nullptr), channelHandle(pChannelHandle), sessionHandle(pSessionHandle)
{
    // OPEN SSH CHANNEL
}

RemoteChannelHandle::~RemoteChannelHandle()
{
    try
    {
        CloseChannel();
    }
    catch (...)
    { }
}

void RemoteChannelHandle::CloseChannel()
{
    if (channel == nullptr)
    {
        return;
    }

    // CLOSE SSH CHANNEL. THROW IF SOMETHING GOES WRONG

    channel = nullptr;
}
  • RemoteChannelHandle 打开一个 SSH 通道,但清理需要两个步骤(关闭 + 空闲)。第一步在 中执行 ~RemoteChannelHandle(),但第二步将在 ChannelHandle 的 dtor 中执行;因此数据成员channelHandle,因为我们需要注入channel它。可以通过执行中的两个步骤来消除此引用~RemoteChannelHandle()
  • sessionHandle持有LIBSSH2_SESSION*打开 SSH 通道的必要条件。既然不想转LIBSSH2_SESSION*了,这个引用就不能去掉了。

当我为 RemoteChannelHandle 定义移动 ctor 时,就会出现问题。我需要清除“移出”实例的成员。但是,没有办法清除引用。那么,在这里做什么呢?

  1. 使用(const) std::shared_ptr而不是参考?我什至可以使用裸指针,因为不涉及所有权。我意识到关于使用引用作为数据成员存在一些争论,但除了移动 ctor 之外,我预计没有其他情况需要重新安装句柄(这就是我首先使用引用的原因)。
  2. 保持引用不变,并专门创建一个“状态”数据成员来检查对象是否处于有效状态(我可以channel != nullptr 用于此目的)?
  3. 还有什么想法吗?

我一直在寻找替代方案,但没有找到明确的答案。当然,这可能意味着实际上没有明确的答案。

谢谢你的时间。

编辑(回复 Mankarse):ChannelHandle 仅用于执行清理的第 2 步。这是一个简化的定义:

class ChannelHandle
{
public:
    ChannelHandle();
    ChannelHandle(ChannelHandle&&);
    ~ChannelHandle();

#ifndef _MSC_VER
    ChannelHandle& operator=(ChannelHandle&&) = delete;
    ChannelHandle(ChannelHandle const&) = delete;
    ChannelHandle& operator=(ChannelHandle const&) = delete;
#endif

    LIBSSH2_CHANNEL* GetChannel() { return channel; }
    void SetChannel(LIBSSH2_CHANNEL* pChannel) { channel = pChannel; }

    void FreeChannel();
private:
    LIBSSH2_CHANNEL* channel;
};

SessionHandle 是LIBSSH2_SESSION*. 它调用libssh2_session_init()ctor 和libssh2_session_free()dtor。其他类似的类负责 SSH 会话的初始化/清理的其他步骤,但这是我们LIBSSH2_SESSION*从 libssh2 获取的地方,而 SessionHandle 拥有它。再一次,一个简化的定义:

class SessionHandle
{
public:
    SessionHandle();
    SessionHandle(SessionHandle&&);
    ~SessionHandle();

    void CloseSession();
    LIBSSH2_SESSION* GetSession() { return session; }

#ifndef _MSC_VER
    SessionHandle& operator=(SessionHandle&&) = delete;
    SessionHandle(SessionHandle const&) = delete;
    SessionHandle& operator=(SessionHandle const&) = delete;
#endif
private:    
    LIBSSH2_SESSION *session;
};
4

1 回答 1

3

你自己回答了这个问题:

我什至可以使用裸指针,因为不涉及所有权。

于 2013-01-24T12:24:56.017 回答