假设以下代码:
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()
,但第二个将在ChannelHandle的dtor;因此数据成员
channelHandle
,因为我们需要将
channel
注入(inject)其中。这个引用可以是通过在
~RemoteChannelHandle()
中执行两个步骤来消除。 sessionHandle
保存打开 SSH 所需的 LIBSSH2_SESSION*
channel 。因为我不想传递 LIBSSH2_SESSION*
,所以这个引用无法消除。
当我为 RemoteChannelHandle 定义一个 move 构造函数时,就会出现问题。我需要清除“move 自”实例的成员。但是,没有办法清除引用。那么,在这里做什么?
(const) std::shared_ptr
而不是引用?我什至可以用裸指针,因为不涉及所有权。我意识到有一些争论
关于使用引用作为数据成员,但除了
move 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*
的 RAII 封装。它在 ctor 上调用 libssh2_session_init()
,在 dtor 上调用 libssh2_session_free()
。其他类似的类负责 SSH session 的初始化/清理的其他步骤,但这是我们从 libssh2 获取 LIBSSH2_SESSION*
的地方,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;
};
最佳答案
你自己回答了这个问题:
关于c++ - 引用数据成员和 move 构造函数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/14499935/