【问题标题】:What is the best way to reset a large object instance in c++在 C++ 中重置大对象实例的最佳方法是什么
【发布时间】:2018-06-14 10:12:02
【问题描述】:

我有一个类对象的实例,我想将其重置为其原始状态。 它有一个经过良好测试的构造函数。 通常我会用像

这样的代码来做到这一点
myObject = MyObject{};

但临时对象太大而无法放入堆栈。

我的选择是

1) 在堆上创建一个默认的临时对象

auto* tempObject = make_unique<MyObject>();
myObject = *tempObject;

2) 使用placement new 就地销毁和重建

myObject.~MyObject();
new( &myObject) MyObject();

3) 将构造函数代码重构为一个单独的重置函数,该函数可从构造函数和其他任何地方调用。

MyObject::MyObject()
{
   reset();
}
//and
myObject.reset();

我特别不喜欢任何选项:1) 在项目中在堆上分配,试图避免不必要的分配 2) 脆弱且有异味 Can I use placement new(this) in operator=? 3) 我很懒,想避免重构,如果我可以。

我想我真正要问的是还有其他我错过的方法吗?理想情况下是否有某种可以应用的优化,这意味着编译器可以省略在堆栈上创建临时项并允许我使用我的原始代码?

【问题讨论】:

  • 项目中堆分配的限制是什么?如果你可以控制时间和多少,它仍然是一个问题吗?您可以为该实例分配一次,并为每次后续重置使用新位置。还是我错过了什么?
  • @Baldrick (2) 的问题是,在抛出构造函数的情况下,您最终可能会得到未定义的对象状态。
  • 我认为 (1) 和 (2) 将涉及编写某种 reset 函数以及为了封装。专用的reset 函数具有明确的目的,并且很可能是非抛出的(与初始构造函数调用不同)。所以(3)似乎是一个显而易见的选择。
  • @VTT 我同意。有时你只需要做硬码。对我来说,唯一可行的选择是准确评估选项 1 的成本并决定是否更可口,

标签: c++ c++14


【解决方案1】:

最好的 - 始终是基于意见的解决方案。

在通常的实践中,如果您使用 OOP 并想要重置对象,请编写 Reset 函数,它会以您希望的方式完成您想要的操作。

您有基类,因此您可以提供相同的模式,而不会破坏封装或制作脆弱、误导性的解决方案。

附言RAII 与僵尸

【讨论】:

  • 要考虑的一件事是,为什么要进行重置。如果这是一个热门对象并且您想节省分配成本,则不一定需要编写重置函数。你也可以写一个初始化,这种方法的优点是你没有无效的对象。
  • @Alex,惰性初始化会导致僵尸对象=)
  • 这取决于你如何做对?如果您在构造函数和 init 中要求所有内容,则可以重用一个对象,而不必调用“reset”,这会生成僵尸对象。
【解决方案2】:

标准容器可能是一种解决方法:

std::vector<MyObject> v(1);    // require a capacity of 1

v.emplace_back();              // ok v[0] is now a ref to a heap constructed object

v.pop_back();                  // destroys the object
v.emplace_back();              // and rebuilds it normally without any (de-)allocation

但这仍然是一个 hack,当我认为正确的解决方案是增加堆栈大小时。所有体面的编译器都有它的选项。

无论如何,重置方法也可以是一个不错且干净的解决方案,只要它从功能的角度来看是有意义的(对象被设计为可重置的)。如果没有,那又是一个 hack。

【讨论】:

    猜你喜欢
    • 2010-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-26
    • 2014-01-01
    • 1970-01-01
    • 2023-03-24
    相关资源
    最近更新 更多