gpt4 book ai didi

c++ - 有没有办法延长 C++ 中临时对象的生命周期?

转载 作者:搜寻专家 更新时间:2023-10-31 01:28:50 25 4
gpt4 key购买 nike

我写了一个作用域守卫,它在作用域退出时重置一个值:

template <class T>
struct ResetGuard
{
T old_value;
T& obj_to_reset;
ResetGuard(T& obj_to_reset, const T& new_value) :
old_value(obj_to_reset),
obj_to_reset(obj_to_reset)
{
obj_to_reset = new_value;
}

~ResetGuard() { obj_to_reset = old_value; }
};

当这个作用域守卫从一个函数返回时,如果它没有被保存,有什么方法可以防止立即销毁作用域守卫?

例如:

int GLOBAL_VALUE = 0;
ResetGuard<int> temporarily_set_global_value(int new_val) {
return { GLOBAL_VALUE, new_val }; //updates the global variable
}
void foo() {
//Ideally, someone calling this function
//Wouldn't have to save the returned value to a local variable
temporarily_set_global_value(15);
std::cout << "GLOBAL_VALUE is " << GLOBAL_VALUE << std::endl;
}

按照现在的编写方式,任何调用其中一个函数的人都必须记住始终将 ResetGuard 保存到局部变量,否则它会立即重置该值。

关于我正在尝试做的事情的一些背景

我正在编写一个库来格式化和操作字符串。我有一个全局变量来控制 float 的格式。我知道全局变量通常是个糟糕的主意,但请多多包涵。

我决定谨慎使用全局变量。使用全局变量的替代方法是传递包含格式规范的对象。这个选项最终被证明是不可行的:我的库旨在与任何提供到 std::string 的隐式转换的对象一起使用。无法将格式化选项(或任何参数,实际上)传递给隐式转换函数。因此,我不得不求助于使用全局变量。

最佳答案

在回答您的问题之前,我想提供在 C++ 中解决此问题的正确方法。

template <class T>
struct [[nodiscard]] ResetGuard
{
T old_value;
T& obj_to_reset;
bool enabled{true};

ResetGuard(T& obj_to_reset, const T& new_value) :
old_value(obj_to_reset),
obj_to_reset(obj_to_reset)
{
obj_to_reset = new_value;
}

ResetGuard(ResetGuard &&rhs)
: old_value(rhs.old_value)
, obj_to_reset(obj_to_reset)
{
rhs.enabled = false;
}
~ResetGuard()
{
if (enabled)
obj_to_reset = old_value;
}
ResetGuard(const ResetGuard &) = delete;
ResetGuard &operator=(const ResetGuard &) = delete;
ResetGuard &operator=(ResetGuard &&) = delete;
};

void foo() {
auto guard = temporarily_set_global_value(15);
std::cout << "GLOBAL_VALUE is " << GLOBAL_VALUE << std::endl;
}

上面的代码包含几个有趣的元素:

  • [[nodiscard]]防止在不创建变量的情况下创建临时变量以确保范围
  • 启用的成员:防止临时的Dtor产生副作用
  • 移动构造函数:移动构造函数允许通过正确的处理将 ResetGuard 移动到不同的范围。在这种情况下,禁用旧的 ResetGuard

作为额外说明,我想将注意力集中在 C++17 扩展(以前允许优化)上,它称为 Guaranteed Copy/Move Elision .这将确保在实践中不会存在额外的临时实例。

回到你的问题:有什么方法可以延长 C++ 中临时对象的生命周期吗?

是的,感谢 N0345 (1993 年的提案)。该提案允许通过常量引用捕获临时对象来对其进行扩展。

const auto &guard = temporarily_set_global_value(15);

但是,我不清楚您总共有多少个实例。但是,如果您将解决方案与移动构造函数一起使用,这将不再是问题。此外,当您使用编译器优化时,此函数可以在 header 中实现时内联。这可以消除所有拷贝。

关于c++ - 有没有办法延长 C++ 中临时对象的生命周期?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51120948/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com