构造函数是否也具有隐式的 this 参数

Does a constructor also have an implicit this parameter

提问人:user12002570 提问时间:4/11/2022 最后编辑:user12002570 更新时间:4/13/2022 访问量:373

问:

我正在学习 C++ 中的类,并且知道非静态成员函数具有隐式此参数。我的第一个问题是构造函数是否也像非静态成员函数一样具有隐式的 this 参数。请注意,我不是在问我们是否可以在 ctor 中使用,因为我已经知道我们可以在 ctor 中使用。thisthis


接下来,我知道在一个类的限定非静态成员函数中,类型是 。对于非静态成员函数(没有 const 限定),其类型为 。同样,在 ctor 内部,类型始终为 。更深层次的问题来了。constXthisconst X*thisX*thisX*

我们知道,当我们调用一个非静态成员函数(比如 like)时,命名对象的地址被隐式传递给该方法的隐式 this 参数。因此,这解释了“在非静态成员函数的情况下,它来自哪里”。obj.func()objfuncthis

现在,让我们将同样的东西应用于构造函数。例如,假设我们使用默认的 ctor 创建一个类对象,例如:X

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

的第二个问题是:同样的事情会发生在 ctor 身上吗?就像,将 的地址传递给默认 ctor 的隐式参数。我目前的理解是 ctor 没有隐含的这个参数。因此,当我们编写 时,地址不会作为参数传递,因为对象尚未创建,因此传递其地址没有意义。但是从标准中我们知道,在 ctor 中,我们可以使用指针。所以我的第二个问题基本上是,如果 ctor 没有隐式参数,那么语句中的参数从何而来?我们知道,在 C++ 中使用任何名称(如变量名称)之前,我们必须为该名称声明。那么声明在哪里呢?编译器是否隐式声明 in 为 ctor?我的意思是,在非静态成员函数的情况下,我可以理解它们将声明作为隐式此参数,但是在 ctors 中会发生什么?在 ctors 内部,我们如何能够在没有声明的情况下使用名称 thisxX x;xthisthisthisthis->p = 0;thisthisthis

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

我的第三个问题是,隐式此参数的概念是实现细节,还是标准说非静态成员函数将具有隐式此参数。

总结

  1. ctors 是否具有隐式此参数?第一个问题也可以表述为“ctors 是否也具有隐式对象参数?

  2. 该标准说我们可以在 ctor 内部使用。但这从何而来。例如,对于非静态成员函数,我们知道它来自隐式 this 参数,但在 ctor 的情况下,由于 ctors 没有隐式参数,我们被允许在 ctor 中使用的参数来自哪里。thisthisthisthisthis

  3. 隐式参数的概念是实现细节,还是标准说所有非静态成员函数都有一个隐式 this 参数,在这种情况下,实现也允许 ctor 具有隐式 this 参数。this

编辑:

这个问题最重要的部分(IMO)是我们如何能够在ctor中使用该名称?例如,当我们写:this

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

在上面的语句中,行为就像一个名字。我们知道,在 C++ 中使用任何名称(如变量名称)之前,我们必须为该名称声明。那么声明在哪里呢?编译器是否隐式声明 in 为 ctor?我的意思是,在非静态成员函数的情况下,我可以理解它们将声明作为隐式此参数,但是在 ctors 中会发生什么?在 ctors 内部,我们如何能够在没有声明的情况下使用名称 thisthisthisthisthis

C++ 构造函数 language-lawyer 这个

评论

1赞 molbdnilo 4/11/2022
“我目前的理解是,ctor 没有隐含的这个参数。”但是它们确实如此,并且它指定了正在构造的对象的位置。
0赞 user12002570 4/11/2022
@molbdnilo谢谢。请随时通过写答案来纠正我。
0赞 user12002570 4/11/2022
@molbdnilo 每句以“我们知道......”开头的句子在我的问题中,至少可以在一本受人尊敬的 C++ 书籍或其他 C++ 资源中找到。当然,这并不意味着它是真的(技术上是正确的)。我的观点是,在写这些句子之前,我已经考虑过了。
1赞 Nicol Bolas 4/11/2022
@Anya:“在上面的陈述中,这表现得像一个名字。它的“行为方式”并不重要;如果它不是名称,则它不是名称,因此不需要遵循“名称”的规则。

答:

2赞 Caleth 4/11/2022 #1

标准中没有“隐式此参数”之类的东西。该标准称其为“隐式对象参数”。

隐式对象参数仅与重载解析相关,它不会“成为”。另外,被定义为具有与成员函数相同的 cv 限定。thisthis

ctors 是否具有隐式此参数?第一个问题也可以表述为“ctors 是否也具有隐式对象参数?

否,来自 [over.match.funcs]

出于重载解析的目的,静态和非静态成员函数都具有隐式对象参数,但构造函数没有。

但这从何而来。this

正在构造的对象。

隐式参数的概念是实现细节,还是标准说所有非静态成员函数都有一个隐式参数,在这种情况下,实现也允许 ctor 具有隐式 this 参数。thisthis

隐式对象参数是重载解析规则的一部分,它不影响 。this

在 ctors 内部,我们如何能够在没有声明的情况下使用名称 this?

this 不是一个名称,它是一个语言关键词。该语言在非静态成员函数中定义为 prvalue 表达式。与位于同一位置的 unqualified-id(命名对象)不同,后者是 glvalue 表达式。this

这就是语言律师的答案。话虽如此,我确实发现“隐式对象参数变成”是一个有用的心智模型。this

回想一下,构造函数(和析构函数)不能是 cv 限定的,因此在构造函数中没有任何内容可以区分,因此它是否存在并不重要。

评论

1赞 Caleth 4/11/2022
@Anya他们没有,因为“隐式此参数”不是标准使用的短语。
1赞 Caleth 4/11/2022
@463035818_is_not_a_number问题被标记为“语言律师”,但我明白你的意思。
1赞 Caleth 4/11/2022
@Anya [class.this] 定义。就像在某个全局包含的标头中没有声明 或 一样,也没有 .它就是这样forifthis
1赞 paxdiablo 4/18/2022
@Anoop,WG21 可能需要清理这个问题:是一个关键字,并且与参数的所有关系充其量都是混乱的,除非它们在函数固有属性的广义上使用“参数”,而不是(隐式)传入的东西。thisthis
1赞 Caleth 5/5/2022
@Mes不,是一个关键词。它被定义为指向成员函数正在操作的对象。编译器可以选择将其实现为额外的指针参数。this
1赞 molbdnilo 4/11/2022 #2

“这个”是一个关键词;它不需要声明,但在非静态成员函数中始终可用。

例如,请参阅此处的标准草案。

该关键字命名一个指针,该指针指向为其调用隐式对象成员函数或计算非静态数据成员的初始值设定项的对象。this

请注意,背后的机制是未指定的。this

3赞 Ben Voigt 4/11/2022 #3

从 C++ 标准的角度来看

该标准仅描述关键字的语义,而不描述其值如何到达那里。这完全被抽象了,实现在实现它方面具有很大的灵活性。this

从理论计算机科学的角度来看

正在构造的对象的地址,通过关键字提供,绝对是对象初始化过程(在 C++ 中称为“构造函数”)的输入。虚拟基子对象的地址也是如此,C++ 也通过关键字提供这些地址,但无法从主输入计算,因此任何此类都必须是附加输入。thisthis

请注意,CS 倾向于在模板参数意义上使用“参数”,而不是动态变量输入。CS 使用“功能”来表示没有副作用的程序。C++ 构造函数不是 CS“函数”,虽然模板化构造函数是可能的(参数化过程),但 的值是普通输入,而不是参数化。this

C++ 构造函数也不是方法 - 没有多态目标类型依赖调度,因此输入尤其不用于调度。this

从参数传递的 ABI 规则的角度来看

C++ 构造函数是一个特殊的成员函数。没有办法为它构造一个函数指针或调用它 C 样式;C 函数的 ABI 要求不适用。

如果平台 ABI 显式描述 C++ 行为,则将有一个或多个规则用于将 的值传递给 C++ 构造函数。这些规则可能会也可能不会指定与其他函数参数等效的机制,但每个面向该平台的符合 ABI 的 C++ 编译器都将按照构造函数的特殊规则的要求传递值。thisthis

值得注意的是,传递给构造函数的 ABI 并不要求等同于传递给其他(非特殊和非静态)成员函数的方式,尽管实际的 ABI 可能对两者使用相同的方法。thisthis