Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/146.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
清空一个C++;对象 我经常在C++对象中添加空< /代码>方法,用类似于下面的代码清除内部状态。 class Foo { private: int n_; std::string str_; public: Foo() : n_(1234), str_("Hello, world!") { } void Empty() { *this = Foo(); } };_C++_Construction - Fatal编程技术网

清空一个C++;对象 我经常在C++对象中添加空< /代码>方法,用类似于下面的代码清除内部状态。 class Foo { private: int n_; std::string str_; public: Foo() : n_(1234), str_("Hello, world!") { } void Empty() { *this = Foo(); } };

清空一个C++;对象 我经常在C++对象中添加空< /代码>方法,用类似于下面的代码清除内部状态。 class Foo { private: int n_; std::string str_; public: Foo() : n_(1234), str_("Hello, world!") { } void Empty() { *this = Foo(); } };,c++,construction,C++,Construction,这似乎比在构造函数中复制代码要好,但我想知道当想要清除对象时,This=Foo()是否是一种常见的方法?等着从背后咬我有什么问题吗?还有其他更好的方法来实现这类功能吗?我想让构造函数调用我的函数: class Foo { private: int n_; std::string str_; public: Foo() { Reset(); } void Reset() { n_ = 1234;

这似乎比在构造函数中复制代码要好,但我想知道当想要清除对象时,This=Foo()是否是一种常见的方法?等着从背后咬我有什么问题吗?还有其他更好的方法来实现这类功能吗?

我想让构造函数调用我的函数:

class Foo
{
private:
    int n_;
    std::string str_;
public:
    Foo()
    {
        Reset();
    }

    void Reset()
    {
        n_ = 1234;
        str_ = "Hello, world!";
    }
};

是的,您不必要先将字符串初始化为空字符串,然后执行赋值,但这更清楚。

< P>也可以考虑使对象不可变,即,当构造时,它们不能被更改。在很多情况下,这可以避免意外的副作用。

考虑使用placement
new

void Empty() {
    this->~Foo();
    new (this) Foo();
}
您的代码调用
operator=
,这可能会导致各种副作用


根据评论编辑。-该代码定义明确,标准明确允许它。如果我有时间的话,我稍后会把这一段发出去。关于
删除
——当然。我的意思是
~Foo()
,这是一个疏忽。是的,罗布也是对的;在这里,调用字符串的析构函数实际上需要销毁对象。

是的,这在性能方面是没有效率的(创建另一个foo对象而不是原地工作),如果在构造函数中分配内存时内存严重泄漏,它会咬你一口

调用this->delete和this=new foo()可以使内存更安全,但速度会很慢

如果您想成为超级快速,请创建一个静态空对象字段,并在重置中memcpy它

如果你想快速地分配一个接一个的属性


如果您想保持合理的样式而不重复,请按照Ates Goral的建议从Ctor调用Reset,但您将失去使用默认参数的更快构造。

潜在问题?你怎么知道这真的是一个Foo呢?

有比你建议的更常见的东西。使用交换

基本上你可以这样做:

T().swap(*this);
由于许多标准容器(所有STL容器?)都有一个固定时间交换方法,因此这是一种清除容器并确保其存储被释放的好方法


类似地,这也是一种“收缩以适应”容器的好方法,但使用复制构造函数而不是默认构造函数。

使用此空方法所做的基本上与手动将新构造的对象分配给变量(空函数所做的事情)相同

就我个人而言,我会删除空方法,并用以下内容替换该方法的所有用途:

// 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();
我真的看不出使用这种空方法有什么好处。它隐藏了它所调用的对象的真实情况,名称也不是最佳选择

如果调用者真的想要一个干净的对象,那么他自己构造对象就没有问题了

这似乎比在构造函数中复制代码要好,但我想知道当想要清除对象时,*This=Foo()是否是一种常见的方法

清除对象并不是一件常见的事情:更常见的情况是,对象(甚至可能是不可变对象)被实例化并包含真实数据,或者它没有被实例化

重置的最常见类型是容器。。。但是,您现在不会编写自己的容器类了,是吗

等着从背后咬我有什么问题吗

是的:

  • 如果这不是一个真正的
    Foo
    ,而是一个
    DerivedFoo
  • 如果
    Foo
    的赋值运算符不存在,或者它有缺陷(例如,如果它没有定义并且默认运算符不好,例如,因为数据成员是裸指针)
有没有其他更好的方法来实现这类目标

是的,也许免费功能会更好(可以避免上述两个问题):

模板空洞重构(T*p)
{
p->~T();
新(p)T();
}

如果构造函数中有动态分配的内存,则这可能是内存泄漏的潜在来源。

以下是我的做法:

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);
}

将swap函数放入与Foo类相同的命名空间中。当用户调用swap来交换两个Foo时,依赖于参数的查找会找到它。您也可以使用swap函数实现
操作符=

哦,天哪。这看起来真是个坏主意。您刚刚删除了this指针(即,您刚刚将该内存返回内存管理器)。如果你幸运的话,你会很快崩溃的。如果没有,您只需将损坏状态提供给谁知道您的程序的哪一部分。不要那样做。你的意思是“this->~Foo()”而不是“删除这个”。即使不删除“this”,它仍然是错误的。您正在对已初始化的内存调用构造函数。对象的std::string字段将被新字段覆盖;它的析构函数不会首先被调用。谢谢你的评论。代码被弄糟了,我现在已经改正了。在我的辩护中,我最初理解错了这个问题,然后重新阅读并编辑了我的帖子。在最初编辑之前,代码实际上是正确的(和现在一样!),我的编辑改进了它。herb sutter不建议这样做:。也就是说,是的,它定义得很好,但一旦你从Foo派生,它就会很难失败。赫伯比我更了解这些东西,还收集了其他问题。Memcpy导致了非POD类型的未定义行为。分配一个新对象并将结果分配给“this”肯定不会达到您的目的。这正是我的想法。这种“对象回收”不会有任何帮助,可能会使维护和调试更加困难。也许“Clear”会是一个更好的名称-许多STL类型都有一个“c”
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);
}