Can I build an object without allocating memory or copying data?

Consider a class 'B' containing simple member charmembers in a specific order.

class B {
    char x1;
    char x2;
    char x3;
    char x4;
}

I have a buffer Athat already contains data in the same order as in B. Another process has already loaded Adata.

char A[4];
  • Is it possible to build an object of the type Bthat contains the data Awithout copying the data by the constructor? That is, I want to "overlay" an object Bon a buffer Aso that I can use methods Bfor data without resorting to the overhead of copying or allocating memory.

  • , 1, - , D, B , B, -?

+4
4

A B, A B. , A , , "", .

struct A
{
    char data[6] = "hi 0/";
    int a = 10;
    int b = 20;
};

struct B
{
    char x1;
    char x2;
    char x3;
    char x4;
    char x5;
    char x6;
};

std::ostream& operator <<(std::ostream& os, B& b)
{
    return os << b.x1 << b.x2 << b.x3 << b.x4 << b.x5 << b.x6;
}

int main()
{
    A a;
    B* b = reinterpret_cast<B*>(&a);
    std::cout << *b;
}

, , . x1 B , , .

, B, ,

struct A
{
    char data[6] = "hi 0/";
    int a = 10;
    int b = 20;
};

struct B
{
    char data[6];
};

Union A, B, B A B.

union Converter
{
    Converter() : a{} {}
    A a;
    B b;
};

std::ostream& operator <<(std::ostream& os, B& b)
{
    return os << b.data;
}

int main()
{
    Converter c;
    std::cout << c.b;
}

, ,

+6

, () . , ( ) , .

, , B ( [[gnu::packed]] gcc - B, , ).

- . , , , . :

const B* b = reinterpret_cast<const B*>(&a[0]);

- . , , . , , .

:

B b;
memcpy(&b, &a[0], sizeof(b));
// use b in non-modifying way
// Compilers usually will not issue a copy here, YMMV
+6

, . :

class B
{
    char x1;
    char x2;
    char x3;
    char x4;
};

char A[4];


B *b = new(A) B; 

b A [4]; , B - .

class D : public B
{
public:
   void MyMethod();
};

D *d = new (A) D;

, , D.

:

#include <new>

#include <iostream>

struct B
{
    char x1;
    char x2;
    char x3;
    char x4;
};

char A[4] = { 'M','e','o','w' };

int main()
{
    B *b = new (A) B;

    std::cout << "The cat " << b->x1 << b->x2 << b->x3 << b->x4 << std::endl;

    return 0;
}

:

-1

Yes, you can; if you are using a new location as specified here ( https://isocpp.org/wiki/faq/dtors#placement-new ), which indicates the memory location for B and is documented here ( https://isocpp.org/wiki / faq / dtors # placement-new ),

But beware of destructor behavior when using this, and initializers in B will randomly overload the data. You must also be very careful about memory alignment and any requirements that objects have in this regard.

Specific warnings to consider on this page:

You are also solely responsible for destructing the placed object. This is done by explicitly calling the destructor:

ADVICE: Don’t use this "placement new" syntax unless you have to. Use it only when you really care that an object is placed at a particular location in memory. For example, when your hardware has a memory-mapped I/O timer device, and you want to place a Clock object at that memory location.

and DANGER: You are taking sole responsibility that the pointer you pass to the "placement new" operator points to a region of memory that is big enough and is properly aligned for the object type that you’re creating. Neither the compiler nor the run-time system make any attempt to check whether you did this right. If your Fred class needs to be aligned on a 4 byte boundary but you supplied a location that isn’t properly aligned, you can have a serious disaster on your hands (if you don’t know what "alignment" means, please don’t use the placement new syntax). You have been warned.

-2
source

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


All Articles