绝对速度最快(希望优雅的)的方式返回一个特定的字符缓冲区给出一个结构类型(Absolute fast

2019-10-28 12:46发布

OK首先,性能是最重要的这里,所以我怀疑地图会工作。 我有结构的(其中约16),如清单

struct A { ... };
struct B { ... }; 
...

每个是不同的,并且每个具有不同的尺寸。

我想知道什么优雅的方式,我们也许能够沿着线做一些事情:

char BufferA[sizeof(struct A)];
char BufferB[sizeof(struct B)];

接着写一些方法或映射到返回缓冲液A,如果你与结构A.工作速度绝对是最重要的,我想使用模板会帮助,但我不知道它的整个事情可以被模板。

更新***对不起,我没有说清楚,缓冲区都是预分配。 我只是需要一个非常快速的方式给出一个结构类型,以获得正确的缓冲区。

更新2 ***对不起,不指定,对准这里是一个重要的特点,我其实做字节对齐使用#pragma组中的每个结构(推,1)

Answer 1:

template<typename X>
struct Buffer
{
    static char *ptr()
    {
        // Note if no alignment is needed for your use then
        // just a simple "static char buf[sizeof(X)]; return buf;"
        // would be sufficient instead of the following.
        union Aligner {
            X x;
            char buf[sizeof(X)];
        };

        static Aligner a;

        return a.buf;
    }
};

struct B
{
    int x, y, z;
};

void foo()
{
    Buffer<B>::ptr()[2] = 12;
}

g++ -O2的代码在上述生成只是一个固定的存储器写操作foo

.globl _Z3foov
    .type   _Z3foov, @function
_Z3foov:
.LFB1:
    .cfi_startproc
    .cfi_personality 0x0,__gxx_personality_v0
    pushl   %ebp
    .cfi_def_cfa_offset 8
    movl    %esp, %ebp
    .cfi_offset 5, -8
    .cfi_def_cfa_register 5

    movb    $12, _ZZN6BufferI1BE3ptrEvE1a+2   <=== this is the assignment

    popl    %ebp
    ret
    .cfi_endproc


Answer 2:

char BufferA[sizeof(struct A)]; 

自动字符数组,不能保证正确对齐。 (取向保证操作员新(some_size)和新的char [some_size],但这些都不是这种情况)。但是,可以在字符数组上使用特定编译器对齐。

我想使用模板会帮助,但我不知道这整个事情可以被模板。 ......我只是需要一个非常快速的方式给出一个结构类型,以获得适当的缓冲。

由于这是基于类型中,模板是走正道。

template<class T>
struct Buffer {
  static char buffer[sizeof(T)] __attribute__((aligned));  // gcc's syntax
};

而且更方便地访问它,而不是缓冲<A> ::缓冲区:

template<class T>
inline
char* get_buffer() {
  return Buffer<T>::buffer;
}

void construct_example() {
  new (get_buffer<A>()) A();
  // same as:
  new (Buffer<A>::buffer) A();
}

这种只允许每个结构类型一个缓冲区 - 这可能是一个问题 - 但它似乎是你所期望的,并希望。



Answer 3:

你可以写有数字的模板参数,和缓冲区的静态成员的模板类。 事情是这样的(未测试):

template <size_t S>
class GlobalBuffer
   {
   static char Buffer[S];
   };

获取缓存与特定的大小,现在可以写成这样一个结构:

GlobalBuffer<sizeof(struct A)>::Buffer;


Answer 4:

如果你是从调用这个代码是什么,从字面上有类型的变量A或什么(而不是某种运行时的开关),那么你可以调用返回缓冲区中的功能时使用,作为一个模板参数。 这将是这个样子:

template <typename T>
char *makebuffer()
{
  return malloc(sizeof(T));
}

然后,在你的代码,你写makebuffer<A>()它会分配正确大小的缓冲区并返回它。



Answer 5:

一个建议:在设计变更。 具有结构返回一个指针到他们未来的缓冲区。

根据您的文章,每个结构都有,一个与之相关联的缓冲区。 这可作为该结构具有将返回相关联的缓冲器的方法进行翻译。

事情是这样的:

struct A
{
  char * get_buffer(void) const;
};

在实现文件中:

static char Buffer_A;  // Static to keep it private to this translation unit.
char * A::get_buffer(void) const
{
  return Buffer_A;
};

这是非常有效的,只要执行去。 这也导致通用性。 你可以把一个纯虚抽象方法在父类返回缓冲区,从而应对您的其他功能指针或引用父类。

注:上面的实现使用外部类声明的自动变量。 在结构内部声明的变量可被置于可具有大小限制比类的外部声明的变量小的堆栈上。 更大的缓冲区也可以使用动态内存声明。 请参阅您的编译器的内存容量限制的文件。



Answer 6:

下面是一些左外野,使用升压融合容器,具体而言, 地图 。

#include <iostream>
#include <boost/fusion/container/map.hpp>
#include <boost/fusion/sequence/intrinsic/at_key.hpp>
#include <boost/array.hpp>

struct A{int a, b, c;};
struct B{double a, b, c;};
struct C{bool a, b, c; };

template <class T>
struct data
{
  data() : buffer() {}

  size_t size() const { return buffer.size(); }

  boost::array<char, sizeof(T)> buffer; // assuming no alignment issues!
};

int main(void)
{
  boost::fusion::map<boost::fusion::pair<A, data<A> >,
                     boost::fusion::pair<B, data<B> >,
                     boost::fusion::pair<C, data<C> >
    > buffer_holder;

  // to access
  std::cout << boost::fusion::at_key<A>(buffer_holder).size() << std::endl; // returns reference to data<A>

  return 0;
}

在这里,所有对每种类型的缓冲区是由单个部件拥有,并且每个缓冲区正确构造,并且可以通过管理data封装(有用的,如果你在一个多线程环境中是)。 不是在视线静态......缺点是没有是的,你可以使用,你可以增加这与编译器标志模板参数的数量限制(我用了30个前)。



Answer 7:

尝试使用工会:在编译时间解决,你可以在你的代码的小修改使用。

#include <iostream>

typedef struct A_
{
    int kk;
    long long pp;
};

//
// with this kind of struct, you have instant access to A contens without memory malllocs, memory leaks,
// you can use in multithread environments, ......
// you don't need virtual tables and so on. You can inherit.......
// you don't spend more memory yhan really necesary
// you don't spend time in functions calling ...
// 

typedef struct A
{
    union
    {
        A_ a;
        char buffer[sizeof(A_)];
    };
};

int main(int argc, char **argv)
{
    A a;

        // we fill the struct information
    a.a.kk = 12;
    a.a.pp = 99991829;

    A b;

        // we access to A buffer without problems
    memcpy(&b, a.buffer, sizeof(b));
    std::cout << "b.a.kk = " << b.a.kk << " b.a.pp = " << b.a.pp << std::endl;
}


文章来源: Absolute fastest (and hopefully elegant) way to return a certain char buffer given a struct type