5

I am learning about classes in C++ and know that non-static member functions have implicit this parameter. My first question is that does constructor also have an implicit this parameter just like non-static member functions. Note that i am not asking whether we can use this inside a ctor as i already know that we can use this inside a ctor.


Next, I know that inside a const qualified non-static member function for a class X, the type of this is const X*. And for a non-static member function(without const qualified), the type of this is X*. Similarly, inside the ctor the type of this is always X*. Here comes the deeper question.

We know that when we call a non-static member function(say like obj.func()), then the address of the object named obj is implicitly passed to the implicit this parameter of the method func. So this explains "where the this comes from in case of non-static member function".

Now, lets apply the same thing to constructors. For example, say we create an object of class X using default ctor like:

X x; //does the default ctor also have an implicit this parameter to which the address of x is passed?

My second question is: Does the same thing happen to ctors? Like, the address of x is passed to an implicit parameter of the default ctor. My current understanding is that ctors don't have an implicit this parameter. So when we write X x;, the address of x is not passed as an argument because the object is not created yet and so it doesn't make sense to pass its address. But from the standard we know that inside a ctor we can use the this pointer. So my second question essentially is that, if ctors don't have an implicit this parameter then where does the this in the statement this->p = 0; come from? We know that before using any name(like variable name) in C++, we must have a declaration for that name. So where is the declaration for this? Does the compiler implicitly declares the this in case of ctor? I mean, in case of non-static member function, i can understand that they have the declaration for this as the implicit this parameter but what happens in ctors? How inside ctors we're able to use the name this without having a declaration for that?

struct Name 
{
    private:
         int p = 0;
         int k = 0;
    void func()  //func is a non-static member function and so have an implicit this parameter
    {
        this->k = 0; // the "this" here comes from implicit this parameter
    }
    Name()
    {
      this->p = 0;  //where does the "this" comes from here since ctor don't have implicit this parameter
    }
    
};

My third question is that is the concept of implicit this parameter an implementation detail or does the standard says that non-static member function will have an implicit this parameter.

Summary

  1. Do ctors have an implicit this parameter? This first question can also be phrased as "Do ctors also have an implicit object parameter?".

  2. The standard says that we can use this inside a ctor. But where does that this come from. For example, in case of a non-static member function, we know that this comes from the implicit this parameter, but in case of ctors, since ctors don't have an implicit this parameter, where does that this that we're allowed to use inside ctor come from.

  3. Is the concept of implicit this parameter an implementation detail or does the standard say that all non-static member functions have an implicit this parameter, in which case, ctors are also allowed by implementations to have an implicit this parameter.

Edit:

The most important part(IMO) of this question is that how are we able to use the name this inside a ctor? For example when we write:

this->p = 0; //here "this" behaves like a name

In the above statement this behaves like a name. And we know that before using any name(like variable name) in C++, we must have a declaration for that name. So where is the declaration for this? Does the compiler implicitly declares the this in case of ctor? I mean, in case of non-static member function, i can understand that they have the declaration for this as the implicit this parameter but what happens in ctors? How inside ctors we're able to use the name this without having a declaration for that?

Jason
  • 36,170
  • 5
  • 26
  • 60
  • 1
    "My current understanding is that ctors don't have an implicit this parameter." But they do, and it designates the location of the object being constructed. – molbdnilo Apr 11 '22 at 08:19
  • @molbdnilo Thanks. Feel free to correct me by writing an answer. – Jason Apr 11 '22 at 08:22
  • @molbdnilo Every sentence starting with "we know that..." in my question can be found atleast in one respectable C++ book or other C++ resources. This doesn't mean that it is true(technically correct) ofcourse. My point is that i have thought about those sentences before writing them. – Jason Apr 11 '22 at 14:05
  • 1
    @Anya: "*In the above statement this behaves like a name.*" It doesn't matter what it "behaves like"; if it's not a name, then it is *not a name* and therefore does not need to follow the rules of a "name". – Nicol Bolas Apr 11 '22 at 15:28

3 Answers3

3

From the perspective of the C++ standard

The standard only describes the semantics of the this keyword and not how its value gets there. That's completely abstracted away and an implementation has great flexibility in making it happen.

From the perspective of theoretical computer science

The address of the object under construction, available via the this keyword, absolutely is an input to the initialization procedure (called "constructor" in C++) for the object. So are addresses of virtual base subobjects, which C++ also makes available via the this keyword but cannot be calculated from the main input, so any such must be additional inputs.

Note that CS tends to use "parameter" with procedures more in the sense of template parameters than dynamic variable inputs. And CS uses "function" to mean a procedure without side effects. A C++ constructor is not a CS "function" and while templated constructors are possible (parametric procedures) the value of this is an ordinary input not a parameterization.

Neither is a C++ constructor a method -- there is no polymorphic target-type-dependent dispatch, and so in particular the this input is not used for dispatch.

From the perspective of ABI rules for parameter-passing

A C++ constructor is a special member function. There's no way to construct a function pointer for it or invoke it C-style; ABI requirements for C functions do not apply.

If the platform ABI explicitly describes C++ behaviors, then there will be one or more rules for passing the value(s) of this to a C++ constructor. Those rules may or may not specify a mechanism equivalent to other function arguments, but every ABI-compliant C++ compiler targeting that platform will pass this values as required by the special rules for constructors.

Notably, the ABI for passing this to a constructor isn't required to be equivalent to how this is passed to other (non-special and non-static) member functions, although practical ABIs may well use the same approach for both.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
2

There's no such thing as "implicit this parameter" in the standard. The standard calls it an "implicit object parameter".

An implicit object parameter is only relevant to overload resolution, it doesn't "become" this. Separately, this is defined to have the same cv qualification as the member function.

Do ctors have an implicit this parameter? This first question can also be phrased as "Do ctors also have an implicit object parameter?".

No, from [over.match.funcs]

For the purposes of overload resolution, both static and non-static member functions have an implicit object parameter, but constructors do not.

But where does that this come from.

The object being constructed.

Is the concept of implicit this parameter an implementation detail or does the standard say that all non-static member functions have an implicit this parameter, in which case, ctors are also allowed by implementations to have an implicit this parameter.

The implicit object parameter is part of the rules of overload resolution, it doesn't influence this.

How inside ctors we're able to use the name this without having a declaration for that?

this is not a name, it is a language keyword. The language defines this in a non-static member function to be a prvalue expression. Unlike an unqualified-id (that names an object) in the same position, which are glvalue expressions.

That's the language-lawyer answer. Having said that, I do find that "implicit object parameter becomes this" is a useful mental model.

Recall that constructors (and destructors) can't be cv qualified, so there isn't anything for it to distinguish in a constructor, so it doesn't matter if it exists or not.

Caleth
  • 52,200
  • 2
  • 44
  • 75
  • When you wrote *"No"* in your answer, you were saying no for the implicit object parameter or the implicit this parameter? I think you were saying "No" for the implicit object parameter. So i suggest you should just quote that part of my first question instead of quoting the whole sentence of my first question, otherwise that is very confusing. – Jason Apr 11 '22 at 08:27
  • @Anya there's no such thing as "implicit `this` parameter". The closest things are implicit object parameter, and `this`. – Caleth Apr 11 '22 at 08:28
  • So non-static member functions don't have an "implicit this parameter" according to the standard? – Jason Apr 11 '22 at 08:30
  • 1
    @Anya they do not, because "implicit this parameter" isn't the phrase used by the standard. – Caleth Apr 11 '22 at 08:31
  • the implicit object parameter in the standard you are refering to is used for overload resultion and because a `const` Constructor doesnt make sense, constructors dont have them, though colloquially one often talks about `this` being an implicit parameter, and while being sloppy, its an mental image that can help to understand. While it is good to make the distinction imho it would be good to also mention the latter – 463035818_is_not_an_ai Apr 11 '22 at 08:55
  • 1
    @463035818_is_not_a_number question is tagged "language-lawyer", but I get your point. – Caleth Apr 11 '22 at 09:00
  • @Caleth This brings me back to the question: *"If ctors don't have an implicit object parameter(as you quoted in your answer) then where does the name `this` that we're using inside the ctor comes from?"* And before you say from the object being constructred, know that what i mean is that: `this` is behaving like a **name** when we use it inside a ctor. And before using any name we must have a declaration for that name. So where is the declaration for the name `this`? Does the compiler implicitly declares `this`? – Jason Apr 11 '22 at 09:29
  • @Anya `this` is *defined* to point to the object that the function is a member of. "In the body of a non-static ([class.mfct]) member function, the keyword `this` is a prvalue whose value is a pointer to the object for which the function is called. The type of `this` in a member function whose type has a *cv-qualifier-seq cv* and whose class is `X` is “pointer to *cv* `X`”." [`[class.this]`](https://timsong-cpp.github.io/cppwp/n4861/class.this#1) – Caleth Apr 11 '22 at 09:36
  • @Caleth I already know this as i have read the page you linked before. But i am asking about how are we able to use the name `this` without having a declaration for it? That is the crux of my question. – Jason Apr 11 '22 at 09:38
  • 1
    @Anya [class.this] *is* the definition. In much the same way that there isn't a declaration of `for` or `if` in some globally included header, nor is there one for `this`. It just *is* – Caleth Apr 11 '22 at 09:40
  • @Caleth Ok, so are you saying that internally the compiler have something like `X* this = &current_object;` inside all the constructors? – Jason Apr 11 '22 at 09:42
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/243780/discussion-between-caleth-and-anya). – Caleth Apr 11 '22 at 09:42
  • @Caleth *"There's no such thing as "implicit this parameter" in the standard."* **seems wrong**. From [expr.call#4](https://timsong-cpp.github.io/cppwp/n4659/expr.call#4): *"If the function is a non-static member function, the **this parameter of the function** shall be initialized with a pointer to the object of the call, converted as if by an explicit type conversion."* – Jason Apr 17 '22 at 13:23
  • 1
    @Anoop, WG21 probably need to clean this up: `this` is a keyword and all relationships to a `this` ***parameter*** are messy at best unless they're using "parameter" in the wider sense of an inherent property of the function rather than something (implicitly) passed in. – paxdiablo Apr 18 '22 at 00:03
  • @Caleth sry but I have a similar question, does the standard say that `this` will be implicit pass into member function as a parameter? – Mes May 05 '22 at 10:29
  • 1
    @Mes no, `this` is a keyword. It is defined to point to the object that the member function is operating on. A compiler *could* choose to implement that as an extra pointer parameter. – Caleth May 05 '22 at 10:36
1

"this" is a keyword; it doesn't need declaring, but is always available in non-static member functions.

See e.g. the draft standard here.

The keyword this names a pointer to the object for which an implicit object member function is invoked or a non-static data member's initializer is evaluated.

Note that the mechanism behind this is unspecified.

molbdnilo
  • 64,751
  • 3
  • 43
  • 82