Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

can memcpy() be used to change "const" member data?

For a struct with const members

struct point { const int x; const int y; };

that is used as member data

struct Foo
{
    point pt{ 0, 0 };
    void move_x(int value);
};

How can Foo::move_x() be written to update Foo::pt? Is it OK to use memcpy()?

#include <memory.h>
void Foo::move_x(int value)
{
    const point pt_{ pt.x + value, pt.y };
    (void) memcpy(&pt, &pt_, sizeof(pt_)); // pt = pt_;
}

This can be safely done using a pointer

#include <memory>
struct Bar
{
    std::unique_ptr<point> pPt_{ new point{ 0, 0 } };
    const point& pt() const {
        return *pPt_;
    }

    void move_x(int value) {
        pPt_.reset(new point{ pt().x + value, pt().y });
    }
};

but the point is then always stored on the heap rather than in Bar.

Note that clients don't really care about point at all:

   Foo foo;
   foo.move_x(314); // (314, 0)

   Bar bar;
   bar.move_x(3141); // (3141, 0)
like image 282
Ðаn Avatar asked Jul 08 '16 12:07

Ðаn


People also ask

Can you overwrite a const?

A variable, const or not, is just a location in memory, and you can break the rules of const and simply overwrite it.

Can a struct member be const?

You can const individual members of a struct. Declaring an entire instance of a struct with a const qualifier is the same as creating a special-purpose copy of the struct with all members specified as const .


1 Answers

This is clearly undefined behavior. Now, "can" this be done? Sure, it can, but only in the sense that the compiler will not complain. But one aspect of C++ is just because the compiler doesn't complain it doesn't mean that the resulting code will work right.

It's only a matter of time before someone writes some code that reads pt, calls move_x(), and then reads pt again.

A modern, optimizing compiler will rightfully assume that because the code is reading const instances, their values cannot change, and then proceed and optimize away the second read from pt, using the data cached from the first read of pt, in the CPU registers.

And then, the hapless programmer will spend a week trying to figure out why the code is clearly not doing what the program says it should be doing.

like image 171
Sam Varshavchik Avatar answered Oct 02 '22 08:10

Sam Varshavchik