An object can be captured by mutable reference, and changed inside a member function which takes the same object as const
.
void g(const int& x, std::function<void()> f)
{
std::cout << x << '\n';
f();
std::cout << x << '\n';
}
int main()
{
int y = 0;
auto f = [&y] { ++y; };
g(y, f);
}
An object is mutated in a scope where it is const
. I understand that the compiler can't enforce constness here without proving that x
and y
are aliases. I suppose all I'm looking for is confirmation that this is undefined behavior. Is it equivalent in some sense to a const_cast
- using a value as non-const
in a context where it should be?
The Captures Clause of the United States Constitution gives Congress the power to "make Rules concerning Captures on Land and Water." A variety of courts, scholars; politicians, and others have recently cited the Clause to support conflicting arguments about the scope of Congress's power to initiate and prosecute war.
Capturing a variable means that variable is passed to the constructor for that class. A lambda can specify whether it's passed by reference or by value.
A capture clause of lambda definition is used to specify which variables are captured and whether they are captured by reference or by value. An empty capture closure [ ], indicates that no variables are used by lambda which means it can only access variables that are local to it.
By default, variables are captured by const value . This means when the lambda is created, the lambda captures a constant copy of the outer scope variable, which means that the lambda is not allowed to modify them. In the following example, we capture the variable ammo and try to decrement it.
Reference or pointer to const doesn't mean the referenced object cannot be modified at all - it just means that the object cannot be modified via this reference/pointer. It may very well be modified via another reference/pointer to the same object. This is called aliasing.
Here's an example that doesn't use lambdas or any other fancy features:
int x = 0;
void f() { x = 42; }
void g(const int& y) {
cout << y;
f();
cout << y;
}
int main() {
g(x);
}
There's nothing undefined going on, because the object itself is not const
, and constness on aliases is primarily for the user's benefit. For thoroughness, the relevant section is [dcl.type.cv]p3
:
A pointer or reference to a cv-qualified type need not actually point or refer to a cv-qualified object, but it is treated as if it does; a const-qualified access path cannot be used to modify an object even if the object referenced is a non-const object and can be modified through some other access path. [ Note: Cv-qualifiers are supported by the type system so that they cannot be subverted without casting (5.2.11). —end note ]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With