Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is modifying the internal bytes of a const object undefined behavior in case it contains another object constructed by placement new?

Consider the following example:

#include <new>

struct FunctionObject
{
    int operator()() // non-const, modifies the state of this object
    {
        i += 1;
        j += 2;
        return i + j;
    }

    int i = 0;
    int j = 0;
};

struct Wrapper
{
    explicit Wrapper(const FunctionObject& input_object)
    {
        constructed_object = ::new (buffer) FunctionObject(input_object);
    }

    ~Wrapper()
    {
        constructed_object->~FunctionObject();
    }

    int operator()() const // const, but invokes the non-const operator() of the internal FunctionObject
    {
        return (*constructed_object)(); // this call modifies the internal bytes of this Wrapper
    }

    alignas(FunctionObject) unsigned char buffer[sizeof(FunctionObject)];
    FunctionObject* constructed_object = nullptr;
};

int test()
{
    const FunctionObject function_object{3, 4};
    const Wrapper object_wrapper{function_object}; // this call modifies the internal bytes of a const Wrapper
    return object_wrapper();
}

A Wrapper contains an internal FunctionObject which is constructed inside the Wrapper by a placement new.

The Wrapper object is const, its operator() is also const, but calling it causes the internal state of the object to be modified. In many cases, similar scenarios are undefined behavior in C++.

The question is, is it undefined behavior in this particular case (~ do I need to mark the buffer as mutable?), or does the C++ standard allow writing code like this?

like image 922
Taras Avatar asked Oct 20 '20 15:10

Taras


1 Answers

This is Undefined Behavior.

From [dcl.type.cv],

Any attempt to modify a const object during its lifetime results in undefined behavior.

Adding the mutable specifier to buffer will allow it to be modified by a const member function.

like image 80
1201ProgramAlarm Avatar answered Oct 17 '22 20:10

1201ProgramAlarm