如何限制构造寿命更长的对象所需的变量范围?

时间:2015-08-27 18:02:45

标签: c++ scope api-design raii

我在堆栈上有一个对象需要另一个对象作为它的构造函数,如下所示:

{
    ObjectDef def(importantData);  // should die as soon as obj is created
    def.setOptionalData(100);

    Object obj(def);  // should live for the remainder of the function body
}

理想情况下,我喜欢将def之类的变量放在自己的范围内。这给了我“def”的名字,并且清楚地表明它已经不再有用了。

例如,result obj我想要对// scope block { int result = complexFunction() + anotherFunction(); printf("the result is %i", result); doMoreThingsWithIt(result); } // "result" is now gone 做些什么:

Object obj

但问题是,我无法在这里做到这一点,我可以看到。 def的构造函数不能在范围之前,因为它的构造函数需要obj,并且它不在范围内,因为def需要比def存活更长时间。

无论如何要将obj的范围限制为短于if Model.exists?(:s => params[:s], :img => params[:image]) do @update = Model.where(:s => params[:s], :img => params[:image]) @update.update_all({num: params[:num], url: params[url].values[0]}) @update.save end else @model = Model.new(s: params[:s], img: params[:image], num: params[:num], url: params[url].values[0]) @model.save end ,或者我是否应该接受它必须保持至少一段时间的范围?

4 个答案:

答案 0 :(得分:8)

你可以使用lambda:

Object obj{[&]{ ObjectDef def{importantData}; def.setOptionalData(100); return def; }()};

如果ObjectDef经常需要它的可选数据集并且这是一种常见模式,请考虑向ObjectDef添加一个构造函数,该构造函数允许设置可选数据或创建一个命名辅助函数做lambda在这里做的工作。

答案 1 :(得分:2)

  

我在堆栈上有一个对象,它需要另一个对象作为它的构造函数。

如果对象的构造需要多个步骤,请为它创建一个工厂函数,并将其视为该类型API的一部分。

这是API设计的一个很好的规则:

  • 当您编写客户端代码时,它将从一开始就是干净的(并且复制粘贴不会为实例化创建重复的代码)

  • 实例化代码变得可测试且可模拟;

  • 如果你需要另一组步骤来实例化Object,你只需创建另一个工厂函数,靠近第一个(自然集中的方式将这种类型实例化到同一个源文件中)。

  • 这将允许您将Object的实例化代码中的任何额外依赖项隐藏到定义Object方法的.cpp文件中(例如,免除必须{客户端代码中的{1}}。

您的客户端代码应始终需要一行来实例化对象:

#include <ObjectDef.hpp>

客户代码:

auto make_object(Data &importantData, int optional = some_default)
{
    ObjectDef def(importantData);  // should die as soon as obj is created
    def.setOptionalData(optional);

    return Object{ std::move(def) }; // def dies here
}

答案 2 :(得分:1)

我想的越多,我认为你需要一个工厂功能/方法。如果这是你需要的唯一对象,lambda方法将正常工作,但如果你需要捕获可选参数或在多个地方使用lamda它可能会变得......凌乱。

我的建议是在Object上定义一个全局函数或一个静态方法(或者可能是一个新的ObjectFactory类),它将获取importaintInfo和一些其他选项,并返回一个完全构造的Object实例。这样你的ObjectDef永远不会比构造Object更长寿。

我真的质疑对指针和堆分配的厌恶,并且知道为什么需要如此快速地销毁ObjectDef会很有帮助。我假设它具有锁定资源的句柄,或者是安全关键,或者您正在为具有少量堆栈内存的系统编程。否则,快速销毁它的好处似乎被调用工厂方法和添加这种方法的代码的开销所抵消。

答案 3 :(得分:-2)

类似的东西:

Object obj;
{
    ObjectDef def(importantData);  // should die as soon as obj is created
    def.setOptionalData(100);

    obj = Object(def);
}