假设以下代码:
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 时,就会出现问题。我需要清除“移出”实例的成员。但是,没有办法清除引用。那么,在这里做什么呢?
- 使用
(const) std::shared_ptr
而不是参考?我什至可以使用裸指针,因为不涉及所有权。我意识到关于使用引用作为数据成员存在一些争论,但除了移动 ctor 之外,我预计没有其他情况需要重新安装句柄(这就是我首先使用引用的原因)。 - 保持引用不变,并专门创建一个“状态”数据成员来检查对象是否处于有效状态(我可以
channel != nullptr
用于此目的)? - 还有什么想法吗?
我一直在寻找替代方案,但没有找到明确的答案。当然,这可能意味着实际上没有明确的答案。
谢谢你的时间。
编辑(回复 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;
};