gpt4 book ai didi

c++ - 如何在静态析构函数中安全地使用 `std::error_category`?

转载 作者:行者123 更新时间:2023-11-30 03:18:10 26 4
gpt4 key购买 nike

考虑使用 LLVM system_category 编写的自定义错误类型实现引用:

#include <iostream>
#include <system_error>

struct my_error_category_type : std::error_category {
char const* name() const noexcept override { return "name"; }
std::string message(int i) const noexcept override{ return "message"; }
~my_error_category_type() {
std::cout << "Destroyed the category" << std::endl;
}
};

std::error_category const& my_error_category() noexcept {
static my_error_category_type c;
return c;
}

现在想象以下使用 std::error_code 处理错误的简单类:

std::error_code do_some_setup() {
return std::error_code(1, my_error_category());
}
std::error_code do_some_cleanup() {
return std::error_code(2, my_error_category());
}

struct MyObj {
void method() {
// this constructs the category for the first time
auto err = do_some_setup();
std::cout << err << std::endl;
}

~MyObj() {
std::cout << "Running cleanup" << std::endl;
auto err = do_some_cleanup();
std::cout << err << std::endl;
}
};

下面的代码给出了报警输出

static MyObj obj;

int main() {
obj.method(); // remove this line, and the output is fine
}
name:1
Destroyed the category
Running cleanup
name:2

请注意 my_error_category_type::message 是如何在被破坏的对象上调用的!

我的问题是:

  1. 在这个被破坏的对象上调用message 安全吗?
  2. 如果没有,是否有办法保持类别的生命周期?我能以某种方式使物体永生吗?
  3. 标准是否对内置 std::system_category() 对象等的生命周期作出任何保证?我上面链接的 LLVM 实现遇到了完全相同的问题。

最佳答案

在调用其析构函数后调用对象方法是不安全的。

问题是如何控制对象的销毁顺序。静态以与初始化相反的顺序销毁,因此 my_error_category_type 将在 MyObj 之前被销毁,因为它的构造函数在 MyObj 构造函数之后被调用。这不是一个问题,需要通过标准来解决,而是架构问题。

所以,我们必须以某种方式控制销毁顺序。最简单的方法是确保 obj 析构函数被更早地调用:

void F() {
MyObj obj;
obj.method();
}

int main() {
F();
}

程序输出:

name:1
Running cleanup
name:2
Destroyed the category

现在 MyObj 析构函数被调用得更早,不是在 main 之后,而是在 F() 结束之后,因为 MyObj 是一个作用域变量,并且它在 F() 完成后被破坏,static my_error_category_type c 在 main 完成时被破坏。

但是如果我们仍然想让 MyObj 静态化,可以使用称为 Nifty Counter Idiom 的技术,它仅在最后一次使用后才有助于破坏静态。但它有其权衡。 link

与静态类似的问题:“静态初始化顺序惨败”(link)。

关于c++ - 如何在静态析构函数中安全地使用 `std::error_category`?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54940071/

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