如何解决移动构造函数和const成员变量
| 我喜欢const成员变量的概念,尤其是当我将C函数包装到类中时。构造函数使用资源句柄(例如文件描述符),该句柄在整个对象生命周期中保持有效,而析构函数最后将其关闭。 (这就是RAII背后的想法,对吗?) 但是使用C ++ 0x move构造函数时,我遇到了问题。由于析构函数也被调用在“ unloaded”对象上,因此我需要防止清理资源句柄。由于成员变量是const,因此我无法分配值-1或INVALID_HANDLE(或等效值)以指示析构函数它不应执行任何操作。 如果将一个对象的状态移到另一个对象,有没有办法不调用析构函数? 例:class File
{
public:
// Kind of \"named constructor\" or \"static factory method\"
static File open(const char *fileName,const char *modes)
{
FILE *handle = fopen(fileName,modes);
return File(handle);
}
private:
FILE * const handle;
public:
File(FILE *handle) : handle(handle)
{
}
~File()
{
fclose(handle);
}
File(File &&other) : handle(other.handle)
{
// The compiler should not call the destructor of the \"other\"
// object.
}
File(const File &other) = delete;
File &operator =(const File &other) = delete;
};
解决方法
不,没有办法做到这一点。我建议,如果您真的很喜欢const的ѭ1变量,则应该有一个非const标志成员变量,该变量指示破坏是否应该做任何事情。
, 这就是为什么您不应该声明所述成员变量“ 2”的原因。
const
成员变量通常没有作用。如果您不希望用户更改FILE*
,则不要为他们提供执行此操作的功能,并且如果您想阻止自己偶然更改它,请标记功能const
。但是,请勿使成员变量本身为“ 2”-因为当您开始使用移动或复制语义时会遇到乐趣。
, 实现move构造函数的典型方法是将要移动的实例的成员清零或使其无效(有关简单示例,请参见MSDN)。因此,我想说的是这里不使用ѭ2,因为它与移动语义的目标不兼容。
, 实际上,我本人今天也遇到了这个问题。不愿意接受“无法完成”和“使用shared_ptr /引用计数”,更多地使用谷歌搜索,我想到了这个基类:
class Resource
{
private:
mutable bool m_mine;
protected:
Resource()
: m_mine( true )
{
}
Resource(const Resource&) = delete;
void operator=(const Resource&) = delete;
Resource(const Resource&& other)
: m_mine( other.m_mine )
{
other.m_mine = false;
}
bool isMine() const
{
return m_mine;
}
};
所有方法和构造函数均受保护,您需要从其继承以使用它。注意可变字段:这意味着后代可以是类中的const成员。例如。,
class A : protected Resource
{
private:
const int m_i;
public:
A()
: m_i( 0 )
{
}
A( const int i )
: m_i( i )
{
}
A(const A&& a)
: Resource( std::move( a ) ),m_i ( std::move( a.m_i ) ) // this is a move iff member has const move constructor,copy otherwise
{
}
~A()
{
if ( isMine() )
{
// Free up resources. Executed only for non-moved objects
cout << \"A destructed\" << endl;
}
}
};
A的字段现在可以为const。请注意,我已经继承了protected,因此用户不会意外地将A强制转换为Resource(或者非常愿意对其进行破解),但是A仍然不是最终的,因此您仍然可以继承自此(从Resource继承的有效理由)例如具有单独的读写访问权限)。这是极少数情况,其中受保护的继承不会自动意味着您的设计有错误;但是,如果您难以理解,则可以使用公共继承。
然后,假设您有struct X
:
struct B
{
const A m_a;
const X m_x;
B(const A&& a,const X& x) // implement this way only if X has copy constructor; otherwise do for \'x\' like we do for \'a\'
: m_a( std::move( a ) ),m_x( x )
{
}
B( const B&& b )
: m_a( std::move( b.m_a ) ),m_x( std::move( b.m_x ) ) // this is a move iff X has move constructor,copy otherwise
{
}
~B()
{
cout << \"B destructed\" << endl;
}
};
请注意,B的字段也可以是const。我们的move构造函数是const。如果您的类型具有适当的move构造函数,则可以在对象之间共享任何已分配堆的内存。
, 引用计数是解决您的问题的标准方法。考虑添加引用计数到您的班级;手动或使用现有工具(如boost shared_ptr)。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。