0

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);
}

Enlico
  • 23,259
  • 6
  • 48
  • 102
Urxtixt
  • 29
  • 1
  • 5
  • 1
    @user2864740 You missed the first line which was hidden in a markdown error by OP. The second most efficient way of hiding important information in a StackOverflow post. – Yunnosch Oct 06 '21 at 05:44
  • 1
    Better get your formatting right, https://stackoverflow.com/editing-help , or you will have more users misreading your posts. – Yunnosch Oct 06 '21 at 05:45
  • The example code looks weird to me! Why we see a pointer default initialization if we have a constructor which initializes the ptr? Why we have auto for a function that returns nothing? And what is the sense of the code at all? To access a constant pointer in a constant function did not mean we access a pointer to a constant value. Why such an obscure example with a class/object only to show that we have const pointers vs pointers to const? – Klaus Oct 06 '21 at 06:15
  • Sorry for the poor formatting, I did try to do it correctly and I didn't realize there were that many formatting issues. Also yes, I was inquiring about the class constructor that also makes use of member initializer lists. As for the weird code, I don't know much about it as it came from a book and did not have much context. I think it mainly used to emphasize a point. – Urxtixt Oct 06 '21 at 07:03
  • What I want to say: If the rest of the book uses also obscure examples for simple things, it will not really be a good book for my point of view! The "always auto" usage and the multiple indirection's only to show that a const pointer points to a non const variable is not really helpful I believe. "Compiles despite function being declared const" is fully pointing to the wrong direction. There is nothing modified inside the object so there is nothing "despite...". More general: If a const function can not do anything, it will never be useful... – Klaus Oct 06 '21 at 07:15

2 Answers2

3
Foo(int* ptr) : ptr_{ptr}{}
  • Declares and defines a constructor for the class Foo,
  • which takes in input a int * (pointer to int),
  • 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 a int*, i.e. a pointer to int;
  • the member function set_ptr_val is const, so it makes the promise that it won't change ptr_ or any other (non-mutable) member;
  • indeed set_ptr_val's body doesn't modify ptr_; what it modifies is the pointed-to int. But that's ok.
Enlico
  • 23,259
  • 6
  • 48
  • 102
2

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.

Ken Wayne VanderLinde
  • 18,915
  • 3
  • 47
  • 72
  • @Yunnosch, actually the OP wrote _I have not seen `int* ptr_{};` and `Foo(int* ptr):ptr_{ptr}{}` before this point. What are these two pieces of code doing?_, so they _are_ asking about that too. – Enlico Oct 06 '21 at 06:05
  • True, admittedly (and I did not see it). But I think being extra clear about which line is explained where does not hurt. But you are right, not strictly needed.... – Yunnosch Oct 06 '21 at 06:09