How to distribute variable sized structures in memory?

I am using C ++ and I have the following structures:

struct ArrayOfThese {
  int a;
  int b;
};

struct DataPoint {
  int a;
  int b;
  int c;
};

In memory, I want to have 1 or more ArrayOfThese elements at the end of each DataPoint. Not always the same number of ArrayOfThese elements in a DataPoint.

Since I have an absurd amount of DataPoints to build and stream over the network, I want all of my DataPoints and their ArrayOfThese elements to be contiguous. Space fading for a fixed number of ArrayOfThese elements is unacceptable.

In C, I would make an element at the end of a DataPoint that was declared as ArrayOfThese d[0];, allocate DataPoint plus enough bytes for all the ArrayOfThese elements that I had, and use a dummy array to index them. (Of course, the number of ArrayOfThese elements should be in the DataPoint field.)

Does C ++ use a new placement and the same 0-length array to crack the correct approach? If so, does the new sentence add that subsequent calls to the new one from the same memory pool will be allocated adjacent?

+3
source share
11 answers

- POD, , C. , , - . , n - , :

DataPoint *p=static_cast<DataPoint *>(malloc(sizeof(DataPoint)+n*sizeof(ArrayOfThese)));

, . , - , , - . , , . , . , DataPoint ArrayOfThese arr[0], :

void *p=malloc(sizeof(DataPoint)+n*sizeof(ArrayOfThese));
DataPoint *dp=new(p) DataPoint;
for(size_t i=0;i<n;++i)
    new(&dp->arr[i]) ArrayOfThese;

, , , , , .

( POD , , , .)

+3

, , C:

void *ptr = malloc(sizeof(DataPoint) + n * sizeof(ArrayOfThese));
DataPoint *dp = reinterpret_cast<DataPoint *>(ptr));
ArrayOfThese *aotp = reinterpet_cast<ArrayOfThese *>(reintepret_cast<char *>(ptr) + sizeof(DataPoint));
+5

, , , , , . , , , , , , .

++ , , std::vector. , , -, . ( ArrayOfThese , std::vector?)

, , undefined, . ? Windows Windows API, , ++, .

ArrayOfThese, fnieto , , new , :

struct DataPoint {
  int a;
  int b;
  int c;
};

template <std::size_t sz>
struct DataPointWithArray : DataPoint {
  ArrayOfThese array[sz];
};

DataPoint* create(std::size_t n)
{
  switch(n) {
    case 1: return new DataPointWithArray[1];
    case 2: return new DataPointWithArray[2];
    case 5: return new DataPointWithArray[5];
    case 7: return new DataPointWithArray[7];
    case 27: return new DataPointWithArray[27];
    default: assert(false);
  }
  return NULL;
}
+2

++ 0X . .

, , , . , , " ++" , Alexandrescu. - , .

+1

, boost::variant . , , , , , , , t .

boost:: variant boost:: any.

, , .

+1
+1

: .

, , : DataPoint ArrayOfThese? , ArrayOfThese DataPoint? ( : ?) ?)

, , , DataPoint, ArrayOfThese DataPoint. , / , . , - .

+1

DataPoint ArrayOfThese? C ++. ,

free(), :

struct ArrayOfThese {
  int a;
  int b;
};


struct DataPoint {
  int a;
  int b;
  int c;
  int length;
  ArrayOfThese those[0];
};

DataPoint* allocDP(int a, int b, int c, size_t length)
{
    // There might be alignment issues, but not for most compilers:
    size_t sz = sizeof(DataPoint) + length * sizeof(ArrayOfThese);
    DataPoint dp = (DataPoint*)calloc( sz );
    // (Check for out of memory)
    dp->a = a; dp->b = b; tp->c = c; dp->length = length;
}

"" , DataPoint :

DataPoint *dp = allocDP( 5, 8, 3, 20 );

for(int i=0; i < dp->length; ++i)
{
    // Initialize or access: dp->those[i]
}
+1

, stl , ?

0

:

  1. ArrayOfThese DataPoint ? int ( )?
  2. ArrayOfThese DataPoint ?

, , , DataPoint + N ArrayOfThese. [], N + 3 a(), b() c(), .

, , , , , fnieto, .

, - , new , . , ( ) .

0

Here is the code I wrote:

#include <iostream>
#include <cstdlib>
#include <cassert>
using namespace std;

struct ArrayOfThese {
  int e;
  int f;
};

struct DataPoint {
  int a;
  int b;
  int c;
  int numDPars;
  ArrayOfThese d[0];

  DataPoint(int numDPars) : numDPars(numDPars) {}

  DataPoint* next() {
    return reinterpret_cast<DataPoint*>(reinterpret_cast<char*>(this) + sizeof(DataPoint) + numDPars * sizeof(ArrayOfThese));
  }

  const DataPoint* next() const {
    return reinterpret_cast<const DataPoint*>(reinterpret_cast<const char*>(this) + sizeof(DataPoint) + numDPars * sizeof(ArrayOfThese));
  }
};

int main() {
  const size_t BUF_SIZE = 1024*1024*200;

  char* const buffer = new char[BUF_SIZE];
  char* bufPtr = buffer;

  const int numDataPoints = 1024*1024*2;
  for (int i = 0; i < numDataPoints; ++i) {
    // This wouldn't really be random.
    const int numArrayOfTheses = random() % 10 + 1;

    DataPoint* dp = new(bufPtr) DataPoint(numArrayOfTheses);

    // Here, do some stuff to fill in the fields.
    dp->a = i;

    bufPtr += sizeof(DataPoint) + numArrayOfTheses * sizeof(ArrayOfThese);
  }

  DataPoint* dp = reinterpret_cast<DataPoint*>(buffer);
  for (int i = 0; i < numDataPoints; ++i) {
    assert(dp->a == i);
    dp = dp->next();
  }

  // Here, send it out.

  delete[] buffer;

  return 0;
}
0
source

Source: https://habr.com/ru/post/1721121/


All Articles