我经常添加一个 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的施工速度快,重复呼叫复位合理的风格

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top