我正在用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函数不是内联的,即使你可以看到,它非常简单。
我知道也许这并没有对我的节目速度产生影响,但我只是想让它更好。
答案 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
只是编译器执行内联的提示,但不需要这样做。
强制内联的唯一方法"将使用预处理器宏,但这很容易出错。错误的是,宏没有做你期望的,而错误的是宏实际上会产生更慢的代码。此外,预处理器宏不能替代成员函数。
因此,如果编译器不想内联,那么 它