132

考虑以下内联函数:

// 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函数,编译器将尝试inline该函数,就好像说明inline符放在其声明中一样?

C++11 标准能保证吗?

4

2 回答 2

160

是([dcl.constexpr],C++11 标准中的 §7.1.5/2):“constexpr 函数和 constexpr 构造函数是隐式内联的 (7.1.2)。”

但是请注意,说明inline符实际上对编译器是否可能内联扩展函数影响很小(如果有的话)但是,它确实会影响一个定义规则,从这个角度来看,编译器需要遵循与constexpr函数相同的规则inline

我还应该补充一点,无论是否constexpr暗示inline,C++11 中的函数规则constexpr都要求它们足够简单,以至于它们通常是内联扩展的良好候选者(主要的例外是那些递归的)。然而,从那以后,规则变得越来越宽松,因此constexpr可以应用于更大、更复杂的功能。

于 2013-01-18T01:55:20.347 回答
47

constexpr不暗示inline非静态变量(C++17 内联变量)

虽然constexpr确实暗示inline了函数,但考虑到 C++17 内联变量,它对非静态变量没有这种影响。

例如,如果您采用我在以下位置发布的最小示例:内联变量如何工作?并删除inline,只留下constexpr,然后变量获得多个地址,这是内联变量避免的主要事情。

constexpr然而,静态变量是隐式内联的。

constexpr暗示inline函数的最小示例

如上所述:https ://stackoverflow.com/a/14391320/895245的主要作用inline不是内联而是允许函数的多个定义,标准引用在:C++ 头文件如何包含实现?

我们可以通过玩以下示例来观察这一点:

主文件

#include <cassert>

#include "notmain.hpp"

int main() {
    assert(shared_func() == notmain_func());
}

不是main.hpp

#ifndef NOTMAIN_HPP
#define NOTMAIN_HPP

inline int shared_func() { return 42; }
int notmain_func();

#endif

非main.cpp

#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

如果我们从 中删除inlineshared_func链接将失败,并显示:

multiple definition of `shared_func()'

因为标头被包含在多个.cpp文件中。

但是如果我们用 替换inlineconstexpr那么它又会起作用,因为constexpr也意味着inline

GCC 通过在 ELF 目标文件中将符号标记为弱来实现这一点:C++ 头文件如何包含实现?

在 GCC 8.3.0 中测试。

于 2019-08-08T07:48:19.330 回答