题
我经常添加一个 Empty
我的 C++ 对象的方法,使用类似于以下的代码清除内部状态。
class Foo
{
private:
int n_;
std::string str_;
public:
Foo() : n_(1234), str_("Hello, world!")
{
}
void Empty()
{
*this = Foo();
}
};
这似乎比在构造函数中复制代码更好,但我想知道是否 *this = Foo()
是想要清除对象时的常见方法吗?这样等着咬我的背有什么问题吗?还有其他更好的方法来实现这种事情吗?
解决方案
我让构造函数调用我的函数:
class Foo
{
private:
int n_;
std::string str_;
public:
Foo()
{
Reset();
}
void Reset()
{
n_ = 1234;
str_ = "Hello, world!";
}
};
是的,你是不必要的初始化字符串为空字符串,然后再做一个任务,但是这是更清晰。
其他提示
可能存在的问题?你怎么知道*这真的是一个富?
你与此空方法做什么,是基本上相同手动分配新构造的对象的变量(即空函数的作用的东西)。
个人而言,我取出空方法,以及与此替换方法的所有用途:
// let's say, that you have variables foo and pfoo - they are properly initialized.
Foo foo, *pfoo;
// replace line "foo.Empty()" with:
foo = Foo();
// replace line "pfoo->Empty()" with:
delete pfoo;
pfoo = new Foo();
// or
*pfoo = Foo();
我真正看到在具有该空方法没有优势。它隐藏了什么是真正发生在它呼吁巫对象,名字是不是最好的选择,要么。
如果主叫方真的希望一个干净的对象 - 他不会有任何问题构造对象本人
此外,考虑使物体不可变的,即的,建造时,它们不能被改变。这可以在很多的情况下从非预期的副作用保存自己。
有东西甚至比你认为什么更常见。使用交换。
基本上,你做这样的事情:
T().swap(*this);
因为许多标准箱(所有的STL容器?)有一个固定的时间交换的方法,这是一个很好的和简单的方法来清除容器中,并确保它的存储被释放。
类似地,它是“缩小以适合”的容器,以及一个很好的方法,但是使用拷贝构造而不是默认的构造方法。
考虑使用放置new
:
void Empty() {
this->~Foo();
new (this) Foo();
}
您的代码调用operator =
这可能会导致各种副作用。
修改强>响应于所述评论。 - 该代码是绝对良好定义的,该标准明确地允许它。我晚些时候发布的段落,如果我找到时间。关于delete
- 当然。我的意思是~Foo()
,这是一个疏忽。是的,罗布是正确的为好;破坏的对象实际上是必要在这里所说的串的析构函数。
这可以是内存泄漏的潜在来源,如果你有在构造一个动态分配的存储器中。
下面就是我如何做到这一点:
class Foo {
private:
int n_;
std::string str_;
public:
Foo() : n_(1234), str_("Hello, world!")
{
}
void Empty()
{
Foo f;
swap(f);
}
void swap(Foo & other) {
std::swap(n_, other.n_);
swap(str_, other.str_);
}
};
void swap(Foo & one, Foo & other) {
one.swap(other);
}
把交换函数到同一命名空间等Foo类。参数依赖查找发现它时,用户做一个电话交换交换两个美孚。您可以使用您的交换功能也实现operator=
。
这似乎比在构造函数中复制代码更好,但我想知道 *this = Foo() 是否是想要清除对象时的常见方法?
清除对象并不是一件常见的事情:更常见的是,对象(甚至可能是不可变对象)被实例化并包含真实数据,或者不被实例化。
最常见的一种事情就是 是 重置将是容器...但是,您现在不会编写自己的容器类,对吗?
这样等着咬我的背有什么问题吗?
是的:
- 如果这真的不是一个
Foo
而是一个DerivedFoo
- 如果
Foo
的赋值运算符不存在,或者它有错误(例如如果未定义并且默认运算符不好,例如因为数据成员是裸指针)。
还有其他更好的方法来实现这种事情吗?
是的,也许免费函数会更好(可以避免上述两个问题):
template<class T> void reconstruct(T* p)
{
p->~T();
new (p) T();
}
是的,这不是有效的在性能方面(创建另一个Foo对象,而不是代替工作),它会咬你,如果你在构造一个讨厌的内存泄漏分配内存。
使其更安全在内存方面将被调用这 - >删除与这个=新FOO() - 但是这将是SLOW
如果你想成为超高速创建静态空对象场和memcpy它复位。
如果你想只是快速通过一个指定的属性之一。
如果你想保持不从构造函数为阿泰古拉尔建议,但你会失去使用默认PARAMS的施工速度快,重复呼叫复位合理的风格