【问题标题】:C++ non-static method foldingC++ 非静态方法折叠
【发布时间】:2015-08-20 21:44:58
【问题描述】:

参考这个问题stackoverflow.com/q/14188612,有没有编译器折叠两个对象的方法实例化的情况?

假设我们有一个带有私有“无状态”方法add 的类,它不会修改类成员:

class Element
{
public:        
    Class(int a, int b) : a_(a), b_(b)
    {
        c_ = add(a, b);
    }

private:
    int add(int a, int b)
    {
        return a + b;
    }

private:
    int a_;
    int b_;
    int c_;
}

int main(void)
{
    Element a(1, 2);
    Element b(3, 4);
}

我们有时是否可以期望add 实际上会被编译为类似static 的方法?或者,更清楚一点,a.add 的地址等于b.addadd 只存储一次)。

这只是一个与理解编译器优化有关的问题。

【问题讨论】:

  • 该方法很可能是内联的,这使得它是否是静态的无关紧要。但是您无法通过检查地址来判断 - 如果您获取函数的地址,那么编译器将为您提供非内联版本的地址,但可能永远不会调用它。查看生成的代码,它是唯一的真相来源。
  • 所有函数总是最多存储一次。

标签: c++


【解决方案1】:

编译器将总是add生成一个二进制方法/函数,
与您拥有多少对象无关。其他任何事情不仅愚蠢,而且不可能:

编译器不可能仅从代码知道/计算在运行时将存在多少对象。虽然您的示例可以实现,但更复杂的程序将根据运行时给出的输入(键盘、文件...)实例化(或不实例化)变量。

请注意,模板可以导致不止一代,代码中使用的每种模板类型都会产生一个(但为此,代码足以了解所有内容,与对象数量无关)。

【讨论】:

    【解决方案2】:

    当您在类定义中定义方法时,通常意味着该方法应该内联到每个调用者中。编译器可以选择不这样做,但很多时候您可能会发现该方法实际上根本不存在于您的输出程序中(当然,在调试版本中并非如此)。

    【讨论】:

      【解决方案3】:

      对于非内联成员函数,标准规定

      一个程序中最多只能有一个非内联成员函数的定义

      C++ 中没有实体b.adda.add 可以从中获取地址。 address-of 运算符需要 C::m(...) 形式的成员函数的限定 ID 以获取函数的地址。在您的情况下, add 的地址是

         auto ptr = &Element::add;
      

      并且独立于任何实例。这给出了一个成员函数指针,它只能用于与对象一起调用函数,例如(a.*ptr)(0,1)(b.*ptr)(2,3) 如果 add 是公共方法。

      【讨论】:

        猜你喜欢
        • 2011-01-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多