提问人:glades 提问时间:5/31/2023 更新时间:5/31/2023 访问量:53
获取 RVO 优化静态的地址
Taking address of RVO-optimized static
问:
在下面的代码中,我尝试将一个单例实例注册到一个保留所有单例的全局数组中(在生产代码中,我可以根据模板参数实例化不同的单例,所以不用担心这个悖论:))。我想知道的是,我是否可以以某种方式获得 lambda 的 to-be 返回类型的地址,无论如何都应该对返回值进行优化,这样我就可以将其注册到全局条目数组中。
这是我得到的:
#include <ranges>
#include <cstdio>
#include <cstdint>
#include <iostream>
namespace rng = std::ranges;
struct MyStruct {
uint32_t a = 0;
};
struct AllStructs {
std::array<MyStruct*, 10> items = { 0 };
std::size_t count = 0;
} g_entries;
auto get_instance() {
static MyStruct instance = []() -> MyStruct{
MyStruct ret{ 15 };
g_entries.items[g_entries.count++] = &ret;
return ret;
}();
return instance;
}
int main() {
[[maybe_unused]] auto instance = get_instance();
std::cout << "my a = " << instance.a << std::endl;
std::cout << "my a from array = " << g_entries.items[0]->a << std::endl;
}
输出:
my a = 15
my a from array = 0
至少它不是这样工作的,因为从数组中收集的条目仍然是 0。我该如何解决这个问题?
进一步说明:
- 我不能在此代码部分中使用动态内存分配!
答:
2赞
Artyer
5/31/2023
#1
NRVO 不是强制性的。但是你可以直接获取结果对象的地址:
auto& get_instance() {
static MyStruct instance = []() -> MyStruct {
MyStruct ret{ 15 };
g_entries.items[g_entries.count++] = &instance;
return ret;
}();
// Or if you don't otherwise need `ret`
static MyStruct instance = []{
g_entries.items[g_entries.count++] = &instance;
return MyStruct{ 15 };
}();
return instance;
}
评论
0赞
glades
6/1/2023
哦,太棒了,我不知道你能做到!我什至不需要捕捉它......
0赞
glades
6/1/2023
我刚刚看到没有执行 RVO,这在我的情况下很糟糕,因为在我的情况下,MyStruct 是一个巨大的数组,它被分配在堆栈上并导致堆栈溢出。有没有办法直接构造到静态?
评论
auto get_instance()
auto& get_instance()
[[maybe_unused]] auto instance = get_instance();
[[maybe_unused]] auto& instance = get_instance();