简体   繁体   English

直接重置结构的内容

[英]Reset directly the content of a struct

I have implemented a function that resets the content of the structure to which a pointer points:我已经实现了一个 function 来重置指针指向的结构的内容:

template <typename Struct>
void initialize(Struct* s)
{
    *s = Struct{};
}

I have performance issues when Struct becomes big (above 10K) because Struct is created in the stack and then assigned to *s .Struct变大(超过 10K)时,我会遇到性能问题,因为Struct是在堆栈中创建的,然后分配给*s I was wondering if I could improve it:我想知道我是否可以改进它:

  1. Is it possible to initialize directly *s without the temporary Struct{} object?是否可以在没有临时Struct{} object 的情况下直接初始化*s
  2. Should I instead evaluate the size of Struct and build it in the heap if it is big?我是否应该评估Struct的大小并将其构建在堆中(如果它很大)?

Thank you in advance先感谢您

Firstly, you should probably use a reference;首先,您可能应该使用参考; not a pointer.不是指针。 The point of this is to avoid null indirection bugs.这样做的目的是避免 null 间接错误。

If the class is trivial and value initialise to zero (which is typically the case for most trivial types), then the optimiser should compile your function into a call to memset , without any need for initialisation of a temporary object.如果 class 是平凡的并且值初始化为零(这通常是大多数平凡类型的情况),那么优化器应该将您的 function 编译为对memset的调用,而无需初始化临时 ZA668CFDE691ACZF456。 So there should be no reason to worry in that case.所以在这种情况下应该没有理由担心。

You could call memset explicitly, although that is technically not portable to exotic systems in case the class contains certain types (for example, null pointer does not necessarily have the representation of zero).您可以显式调用memset ,尽管从技术上讲,如果 class 包含某些类型(例如,null 指针不一定具有零表示),这在技术上不能移植到外来系统。

Is it possible to initialize directly *s without the temporary Struct{} object?.是否可以在没有临时 Struct{} object 的情况下直接初始化 *s?

Yes, if you're willing to change the requirements of the function.是的,如果您愿意更改 function 的要求。 Currently it works for classes that are default constructible and move assignable.目前它适用于默认可构造和可移动分配的类。

You can avoid creation of a temporary object if you modify the pointed object directly.如果直接修改指向的 object,则可以避免创建临时 object。 In following example, there are no temporaries of type Struct created:在以下示例中,没有创建Struct类型的临时对象:

constexpr void
initialize(Struct& s)
{
    s.member1 = T1{};
    s.member2 = T2{};

To make this generic, the operation could be performed in a member function.为了使其通用,可以在成员 function 中执行操作。 Thus, you could specify a requirement that the pointed class has a member function with particular name and no parameters:因此,您可以指定一个要求,即指向的 class 具有一个具有特定名称且没有参数的成员 function:

s.clear();

You can combine both approaches for types which they apply to:您可以将这两种方法组合用于它们适用的类型:

template<class Struct>
constexpr void
initialize(Struct& s)
{
    if constexpr (std::is_trivially_copyable_v<Struct>) {
        // alternative 1, if you trust your optimiser
        s = Struct{};
        // alternative 2, if you doubt the quality of the optimiser
        //    technically may have different meaning on exotic systems
        std::memset(&s, 0, sizeof s);
    } else {
        s.clear();
    }
}

If you need this to work with some classes that conforms to neither requirement, then you'll need to specialise the template.如果您需要它来处理一些不符合这两个要求的类,那么您需要专门化模板。

Should I instead evaluate the size of Struct and build it in the heap if it is big [10K]?我是否应该评估 Struct 的大小并将其构建在堆中(如果它很大 [10K])?

You generally should avoid having public classes that large entirely.您通常应该避免完全拥有这么大的公共课程。 If you need such large storage, you could wrap it in a type that allocates it dynamically.如果您需要如此大的存储空间,您可以将其包装在动态分配的类型中。 Something like this:像这样的东西:

class Struct
{
private:
    struct VeryLarge{/.../};
    std::unique_ptr<VeryLarge> storage;
public:
    // public interface

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM