3 ms·
> Why is f.x a const object even when accessed through a non-const variable? Because the member is const. It's a bit strange example because there's no reason
by judofyr 5y ago
> Why is f.x a const object even when accessed through a non-const variable?
Because the member is const.
It's a bit strange example because there's no reason to have mutable pointer to a struct with only const members. A better example would maybe be:
struct foo{ int const x; int y; };
void some_func(foo *f) {
foo.y = 0;
}
int bar() {
foo f { 123, 456 };
some_func(&f);
return f.x; // must always return 123
}
EDIT: On second thought I'm also a bit confused. Wouldn't this be a "safe" way of modifying `f.x`?
void some_func(foo *f) {
*foo = foo { 5, 5 }; // probably wrong syntax? I don't write so much C/C++
}
- mikieng 5y agoRegarding your EDIT: that is not a valid way of modifying x. When you try to assign a new foo that way, what you are implicitly doing is calling the copy assignment operator. This normally works by copying each field from the input object to the destination object, but, since the field x is const, it cannot be re-assigned to the input object's x. In fact, very often the compiler will generate a copy assignment operator implicitly for you, but not in this case, because it can't copy values into a constant field. Also, since you have a local pointer f within some_func, so re-assigning a new object of type foo to it will not alter the original foo. This is not implied by your original comment but it's something one could wonder.
- codeflo 5y agoI think you have to do void some_func(foo *f) { new(f) foo { 5, 5 }; } because no assignment operator is generated for a struct with a const member.
- nyanpasu64 5y ago> no assignment operator is generated for a struct with a const member. I wanted to use const fields to enforce the logical invariant that a field never changes for the lifetime of an object, until the entire object is overwritten by a newly constructed object. Unfortunately C++ deleting the move-assignment operator means it's no longer practical to do so (though you can use placement-new for POD data where it's safe to not run the destructor, and even then it's obscure and will leak memory and possibly is UB as soon as you add an owning type). Instead, I keep a mutable field and have to remember to never mutate it when writing hundreds of lines of method implementations, and when I come back to the code months later and edit it, and someday I may slip up. Rust has no const fields at all.