创建一个函数返回临时对象内联?

时间:2014-05-10 04:50:11

标签: c++ c++11 visual-studio-2013 inline

我正在用c ++编写一个新容器的迭代器。当我调用begin()和end()函数(都非常短)时,我希望编译器使其成为内联函数。但它没有。我想也许是因为迭代器作为临时对象返回,需要复制它。我想也许我可以在c ++ 11中使用RValue参考,但我并不熟悉它。那么有没有办法让它内联?

代码是这样的(不完全相同,但我认为如果这个版本有效,我的代码也可以工作)。

我使用的是VC ++ 2013 CTP,我已经更改了编译选项,但它也没有用。

class Pointer
{
public:
    Pointer(int* p) : p(p)
    {
        (*p)++;
    }
    Pointer(const Pointer& pointer) : p(pointer.p)
    {
        (*p)++;
    }
    Pointer& operator =(const Pointer& pointer)
    {
        (*p)--;
        p = pointer.p;
        (*p)++;
    }
    int* p;
    ~Pointer()
    {
        (*p)--;
    }
    static Pointer create(int& p)
    {
        return Pointer(&p);
    }
    static Pointer create2(int& p)
    {
        return create(p);
    }
};

int main()
{
    int p = 0;
    Pointer pointer = Pointer::create2(p);
}

这里的create和create2函数不是内联的,即使你可以看到,它非常简单。

我知道也许这并没有对我的节目速度产生影响,但我只是想让它更好。

3 个答案:

答案 0 :(得分:5)

有些情况下,microsoft的编译器无法内联函数:

http://msdn.microsoft.com/en-us/library/a98sb923.aspx

  

在某些情况下,编译器不会出于机械原因内联特定函数。例如,编译器不会内联:

     

一个函数,如果它会导致混合SEH和C ++ EH。

     

当-GX / EHs / EHa打开时,带有复制构造对象的一些函数通过值传递。

     

当-GX / EHs / EHa打开时按值返回可展开对象的函数。

     

在没有-Og / Ox / O1 / O2的情况下编译时使用内联汇编的函数。

     

带有可变参数列表的函数。

     

带有try(C ++异常处理)语句的函数。

因为函数按值返回Pointer并且它有一个析构函数,所以函数不能内联。

除了更改Pointer类之外,没有什么可以真正做到的。 Rvalue refs在这里没有帮助。我只是保留代码,如果你需要在最终产品中获得更好的性能,可以试试另一个编译器。

RVO可能会在这里发生,但它没有区别,因为复制的成本太小了。

答案 1 :(得分:2)

answer by Timo对于 /EH??标志的任何组合是正确的(并且/EH?? 必须指定以允许任何有用的异常处理),特别是MSVC Studio-2015以及Studio-2017 15.1和15.2版本如果存在D&#tor,则将不会内联函数调用。

但是,我最近找到了UserVoice Issue -- Support inlining for functions returning unwindable objects -- for this :( 12月',2016)

  

在深度模板化的代码中,调用a似乎很常见   只是将参数转发到另一个函数的函数,   它再次将参数转发到另一个函数中   再做一次转发,等等。据我所知,目前的版本   如果返回一个,Visual C ++无法内联这样的函数   具有非平凡析构函数的对象,只要启用了异常。   这通常会使性能受到打击,尤其是当水平时   转发是不可避免的深刻,有很多争论   不那么小的尺寸。我非常希望即将推出的Visual C ++ 2017   已经解决了这个问题,但似乎没有。

一条评论说明它将在VS2017 v15 .3 中修复,并链接到connect issue,其中的评论声明:

  

内联限制是因为存在异常处理。我们最近改进了内联器,它现在可以在你提供的情况下内联std :: make_unique。请下载最新的VS 2017版本进行试用。请注意,在VS 2017 RTM中,默认情况下此新内联已关闭,但您可以通过向cl.exe添加标记/d1ReturnUdtEHInline /d2ReturnUdtEHInline来启用它。它将在未来版本中默认启用。

请注意,/d1/d2开关是编译器前/后端的未记录的开关。

  

您应该期望在VS 2017 15.3版本中默认启用它。

所以,也许希望这将在VS2017 U3中实际修复。

要试验的两个简短的Godbolt示例:

答案 2 :(得分:1)

在C语言中,根本没有办法强制内联。 inline只是编译器执行内联的提示,但不需要这样做。

强制内联的唯一方法"将使用预处理器宏,但这很容易出错。错误的是,宏没有做你期望的,而错误的是宏实际上会产生更慢的代码。此外,预处理器宏不能替代成员函数。

因此,如果编译器不想内联,那么