Is the code below bad practice or undefined behavior? Essentially i am calling a const func to modify a member which is not marked as mutable. Link to demo
Credits to Mehrdad for inspiring this question (his question Does this code subvert the C++ type system?) and david for minor demo improvements.
#include <iostream>
using namespace std;
struct BreakConst
{
int v;
int *p;
BreakConst() { v = 0; p = &v; }
void break_stuff() const { ++*p; }
};
void f(const BreakConst& bc) {
bc.break_stuff();
}
Original Version that most answers are based on:
Answered by David Rodríguez, jpalecek, Mehrdad
Yes: This is “Undefined behavior”
int main()
{
const BreakConst bc;
cout << bc.v << endl; // 0
bc.break_stuff(); // O:)
cout << bc.v << endl; // 1
return 0;
}
New Alternative Question:
Answered by Mehrdad
No: This is not “Undefined behavior”
int main()
{
BreakConst bc;
cout << bc.v << endl; // 0
f(bc); // O:)
cout << bc.v << endl; // 1
return 0;
}
Result:
0
1
In this case, I’d say it’s undefined behaviour.
bcis aconstobject, so are all its subobjects (lessmutables)1, thereforebc.vshould be, too and modifying aconstobject, however achieved, is UB2.[1] C++03 3.9.3/3:
[2] C++03 7.1.5.1/4:
EDIT responding to the edit of the question: No, the modified version of the code does not cause undefined behavior. It may be bad practice, but actually may be useful at times. You can eg. use it to implement iterators to your classes via const-iterators (DRY):
Of course that relies on the fact that
iterators can only be made from mutable containers, that the const and non-const versions do not differ (no COW and such) etc., but that is fairly common.