I saw this code in the book "C High Performance" by Bjorn Andrist and Viktor Sehr.
The code example is actually used to show the point that "Compiles despite function being declared const
!", and I am aware of this. However, I have not seen int* ptr_{};
and Foo(int* ptr):ptr_{ptr}{}
before this point. What are these two pieces of code doing, especifically Foo(int* ptr):ptr_{ptr}{}
?
The entire code snippet used as an example was this:
class Foo {
public:
Foo(int* ptr):ptr_{ptr}{}
auto set_ptr_val(int v) const {
*ptr_ = v; // Compiles despite function being declared const!
}
private:
int* ptr_{};
};
int main(){
auto i = 0;
const auto foo = Foo{&i};
foo.set_ptr_val(42);
}
CodePudding user response:
Foo(int* ptr) : ptr_{ptr}{}
- Declares and defines a constructor for the class
Foo
, - which takes in input a
int *
(pointer toint
), - and initializes the member variable
ptr_
via the member initializer list; - it does nothing more, so the body is emtpy,
{}
.
int* ptr_{};
uses one possible syntax of value initialization to zero initialize ptr_
; since it of type int*
, it will be inialized with nullptr
, so that's equivalent to int* ptr_{nullptr};
.
As regards the point they're making, I think they are overstressing a normal observation thus making it look like a special rule:
- the class has a member named
ptr_
which is aint*
, i.e. a pointer toint
; - the member function
set_ptr_val
isconst
, so it makes the promise that it won't changeptr_
or any other (non-mutable
) member; - indeed
set_ptr_val
's body doesn't modifyptr_
; what it modifies is the pointed-toint
. But that's ok.
CodePudding user response:
Let's start with the easy one: int* ptr_{};
. This just defines a member variable named ptr_
that is a pointer to an int
. The {}
just initializes it to null.
Next up is Foo(int* ptr):ptr_{ptr}{}
. If we format this differently it becomes much clearer what is going on:
Foo(int* ptr)
: ptr_{ptr}
{
}
This is a constructor, as evidenced by the use of the class name Foo
. It takes a single argument (which is what enables the use of Foo{&i}
inside of main()
). On from there, the colon (:
) begins an member initializer list, which is where member variables can be initialized. In general this can be a comma-separated list of member initializers. The code ptr_{ptr}
is one such member initializer, and it initializes the member variable ptr_
to have the same value as the argument ptr
. I.e., ptr_
will point to the same int
as ptr
. Finally we have the constructor body, which in this case is empty so is composed of nothing but braces.