gpt4 book ai didi

c++ - 具有没有任何构造函数的标准布局结构的 RVO

转载 作者:可可西里 更新时间:2023-11-01 16:11:14 24 4
gpt4 key购买 nike

我有一个表示二进制消息的结构。我想编写一个函数来从缓冲区(无论是文件还是套接字,都无所谓)中获取下一条这样的记录:

template <typename Record>
Record getNext();

现在,我可以这样写:

template <typename Record>
Record getNext() {
Record r;
populateNext(reinterpret_cast<char*>(&r), // maybe ::read()
sizeof(r)); // or equivalent
return r;
}

这很好,让我受益于 RVO。但是,它将调用 Record 的默认构造函数,它可能由具有非平凡默认构造函数的类型组成,这些默认构造函数的工作我想避免——这些不一定是 POD 类型,但它们 < em>是标准布局。

有没有一种方法可以编写 getNext(),从而避免在 Record 上使用任何构造函数(默认或复制/移动)?理想情况下,当用户调用时:

auto record = getNext<Record>();

缓冲区被直接读入record的内存中。这可能吗?

最佳答案

no_initno_init_t 类型的常量。

如果您从 no_init_t 构造一个 pod,您会得到一个未初始化的 pod,并且(假设省略)没有什么可做的。

如果您从 no_init_t 构造一个非 pod,您必须覆盖一个构造函数,并使其不初始化数据。通常 class_name(no_init_t):field1(no_init), field2(no_init){} 会做,有时 class_name(no_init_t){} 会做(假设所有内容是 pod )。

但是,从每个成员的 no_init 构建可以作为成员确实是 pod 的完整性检查。从 no_init 构造的非 pod 类将无法编译,直到您编写 no_init_t 构造函数。

这(必须 no_init 每个成员构造函数)确实会产生一些烦人的 DRY 失败,但我们没有得到反射,所以你会重复自己并喜欢它。

namespace {
struct no_init_t {
template<class T, class=std::enable_if_t<std::is_pod<T>{}>>
operator T()const{
T tmp;
return tmp;
}
static no_init_t instance() { return {}; }
no_init_t(no_init_t const&) = default;
private:
no_init_t() = default;
};
static const no_init = no_init_t::instance();
}


struct Foo {
char buff[1000];
size_t hash;
Foo():Foo(""){}
template<size_t N, class=std::enable_if_t< (N<=sizeof(buff)) >>
Foo( char const(&in)[N] ) {
// some "expensive" copy and hash
}
Foo(no_init_t) {} // no initialization!
};
struct Record {
int x;
Foo foo;
Record()=default;
Record(no_init_t):
x(no_init), foo(no_init)
{}
};

现在我们可以用no_init构造Record,它不会被初始化。

每个 POD 类都没有被初始化。每个非 POD 类都必须提供一个 no_init_t 构造函数(并且可能尽可能地实现非初始化)。

然后你 memcpy 就在它上面。

这需要修改您的类型及其包含的类型,以支持非初始化。

关于c++ - 具有没有任何构造函数的标准布局结构的 RVO,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30736965/

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