Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Constness of captured reference

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?

like image 318
scry Avatar asked Feb 19 '14 22:02

scry


People also ask

What is a capture clause?

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.

What does capture mean in C++?

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.

What is lambda capture clause?

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.

Why is lambda capture Const?

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.


1 Answers

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 ]

like image 165
Igor Tandetnik Avatar answered Sep 23 '22 03:09

Igor Tandetnik