考虑以下内联函数:
// Inline specifier version
#include<iostream>
#include<cstdlib>
inline int f(const int x);
inline int f(const int x)
{
return 2*x;
}
int main(int argc, char* argv[])
{
return f(std::atoi(argv[1]));
}
和constexpr等效版本:
// Constexpr specifier version
#include<iostream>
#include<cstdlib>
constexpr int f(const int x);
constexpr int f(const int x)
{
return 2*x;
}
int main(int argc, char* argv[])
{
return f(std::atoi(argv[1]));
}
我的问题是:constexpr
说明符是否意味着inline
说明符,如果将非常量参数传递给constexpr
函数,编译器将尝试{ {1}}函数就像inline
说明符放在声明中一样?
C ++ 11标准是否保证?
答案 0 :(得分:113)
是([dcl.constexpr],C ++ 11标准中的§7.1.5/ 2):“constexpr函数和constexpr构造函数是隐式内联的(7.1.2)。”
但请注意,inline
说明符对编译器是否可能内联扩展函数的影响确实非常很少(如果有)。但是,它会影响一个定义规则,从这个角度来看,编译器必须遵循constexpr
函数的相同规则作为inline
函数。
我还应该补充一点,无论constexpr
隐含inline
,C ++ 11中constexpr
函数的规则要求它们足够简单,以至于它们通常是内联的良好候选者扩展(主要的例外是递归的)。然而,从那时起,规则逐渐变得松散,因此constexpr
可以应用于更大,更复杂的功能。
答案 1 :(得分:8)
interval: null
并不暗示constexpr
用于非静态变量(C ++ 17内联变量)
考虑到C ++ 17内联变量,尽管inline
对于功能确实暗示constexpr
,但对非静态变量没有影响。
例如,如果您以我在How do inline variables work?上发布的最小示例为例,并删除inline
,仅保留inline
,则该变量将获得多个地址,这是主要的内联变量避免。
constexpr
静态变量是隐式静态的。
constexpr
暗示功能的constexpr
的最小示例
如https://stackoverflow.com/a/14391320/895245所述,inline
的主要作用不是内联而是允许对函数进行多个定义,标准引号位于How can a C++ header file include implementation?
我们可以通过以下示例进行观察:
main.cpp
inline
notmain.hpp
#include <cassert>
#include "notmain.hpp"
int main() {
assert(shared_func() == notmain_func());
}
notmain.cpp
#ifndef NOTMAIN_HPP
#define NOTMAIN_HPP
inline int shared_func() { return 42; }
int notmain_func();
#endif
编译并运行:
#include "notmain.hpp"
int notmain_func() {
return shared_func();
}
如果我们从g++ -c -ggdb3 -O0 -Wall -Wextra -std=c++11 -pedantic-errors -o 'notmain.o' 'notmain.cpp'
g++ -c -ggdb3 -O0 -Wall -Wextra -std=c++11 -pedantic-errors -o 'main.o' 'main.cpp'
g++ -ggdb3 -O0 -Wall -Wextra -std=c++11 -pedantic-errors -o 'main.out' notmain.o main.o
./main.out
中删除inline
,则链接将失败,并显示以下信息:
shared_func
因为标头包含在多个multiple definition of `shared_func()'
文件中。
但是如果我们将.cpp
替换为inline
,它将再次起作用,因为constexpr
也意味着constexpr
。
GCC通过在ELF目标文件上将符号标记为弱符号来实现:How can a C++ header file include implementation?
在GCC 8.3.0中进行了测试。