C ++ 11中成员函数的值类别属性是什么?

时间:2019-03-16 15:43:27

标签: c++ c++11 c++17

cppreference开始,从C ++ 11开始了解值类别,我很难理解将成员函数设为prvalues的动机。

  

a.m,对象表达式的成员,其中m是...非静态成员函数

除了它们不是真正的prvalue之外,因为它们的唯一属性是可以调用它们。

  

表达式a.mf ... [和朋友] ...被归类为prvalue表达式,但是它们不能用于任何目的,除非用作函数的左手参数。呼叫接线员

此外,C ++ 17临时实现如何与成员函数的值类别交互?从cppreference

  

在对类prvalue执行成员访问时发生临时实现...

通常来说,函数是不可修改的左值对我来说更有意义。也就是说,它们具有定义的位置。我了解在虚拟成员函数的情况下没有编译时位置,因此我明白了为什么这种情况不会是左值。我还看到,一个临时物化类的成员函数也可能没有编译时位置,并且可能不是左值,尽管该成员函数仍在某处编译并具有一个位置(C ++可能根本无法在该位置引用该位置)。语言级别)。

对我来说,最令人困惑的是,编译器最终不会将非虚拟成员函数与任何其他函数区别对待。唯一的区别是名称修饰。那么为什么它们在世界上属于不同的价值类别?

必须有一些令人信服的理由,即当成员函数具有明确定义的位置时,它们不是左值。这是一些真正的浑水。有人可以提供动力和澄清吗?

2 个答案:

答案 0 :(得分:1)

非静态成员函数具有“定义明确的位置”。在编译时,虚拟成员函数的“位置”通常是未知的。甚至不理会,成员函数的“位置”从未真正在C ++中处理过。

是的,有“指向成员函数的指针”,但是请注意,这些类型不能 转换为指向其他事物的指针。该标准甚至不允许实现允许转换为整数并通过reinterpret_cast进行转换,这与对普通指针的处理方式相同。从内存地址的角度来看,它们不是“指针”。

成员函数所具有的位置与其他C ++事物所具有的含义不同。因此,将它们分类为prvalue是有意义的。

  

此外,C ++ 17临时实现如何与成员函数的值类别交互?

临时物化适用于对象;成员函数不是对象。请注意您所引用的内容:“在对 class prvalue 进行成员访问时”。成员函数不是类,因此不适用。

  

对我来说,最令人困惑的是,编译器最终不会将非虚拟成员函数与其他函数区别对待。

编译器如何实现标准无关紧要。标准将它们声明为prvalue,所以它们就是它们。

答案 1 :(得分:0)

经过一番思考,很明显为什么成员函数作为左值是荒谬的。任何成员函数都有一个隐式参数参数this,该参数是从C ++语言级别抽象出来的。结果,成员函数的左值将没有this的上下文,并且将无用,因为将无法调用它。

此外,虚拟类还有一个额外的隐藏虚拟指针成员。虚拟成员函数已经不能是左值,因为它们在编译时是不确定的,但是虚拟指针成员也将丢失,因为它是从this中检索的,因此这是第二个原因,即虚拟成员函数不能成为左值。

我认为这是C ++设计中的一个错误,并且将成员函数配音为“ prvalues”是一种掩盖。如果没有隐藏参数,则成员函数将是左值(可通过将引用传递给对象来调用)。此外,如果没有隐藏的类成员,并且没有隐藏虚拟表,则可以查询虚拟表以在运行时检索虚拟函数的左值(当前在C ++中根本不可能)。当然,将指定虚拟功能的实现,但这并不是一件坏事,罕见的事情,也不是史无前例的事情,因为存在RVO和复制省略。