constexpr은 인라인을 의미합니까?


105

다음 인라인 함수를 고려하십시오.

// 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 표준이 보장합니까?


5
'컴파일러가 함수를 인라인하려고합니다'는 inline지정자가 하는 일이 아닙니다 . (아니면 내가 당신의 말씨를 오해.)
뤽 덴톤

5
inline지정은 더 이상 함께 할 수있는 아무것도 없다 인라인
K-가면 무도회

2
이 질문 inline은 인라이닝과 직접적으로 관련된 잘못된 가정에 근거합니다 . 따라서 constexpr지정자는 의미가 존재하지 않기 inline때문에 의미에서 지정자 의미하지 않습니다.
Christian Rau

답변:


139

예 ([dcl.constexpr], C ++ 11 표준의 §7.1.5 / 2) : "constexpr 함수 및 constexpr 생성자는 암시 적으로 인라인 (7.1.2)입니다."

참고 그러나 것을 inline지정 정말이 매우 컴파일러 가능성이 함수 인라인 여부를 확장하는 것입니다 여부에 (있는 경우) 거의 영향을. 그러나 이는 하나의 정의 규칙에 영향을 미치며 그 관점에서 컴파일러는 constexpr함수와 동일한 규칙을 따라야합니다 inline.

또한 constexpr암시에 관계없이 C ++ 11의 함수에 inline대한 규칙 constexpr은 인라인 확장을위한 좋은 후보가 될 수있을 정도로 간단해야합니다 (주요 예외는 재귀적인 것임). 그러나 그 이후로 규칙은 점차 완화 constexpr되어 훨씬 더 크고 복잡한 기능에 적용될 수 있습니다.


상수 표현식이 컴파일 타임에 평가된다는 생각을 감안할 때 대부분의 constexpr함수 사용으로 인해 코드 생성이 전혀 발생하지 않는다고 가정 합니다.
Kerrek SB

11
@KerrekSB constexpr함수는 컴파일 타임에 잠재적으로 평가됩니다. 그러나 C ++ 14 표준은 런타임에 호출 될 가능성이 높은 표준으로 가득 차 있습니다. 예 :std::array<T,N>::at
Eponymous

@Eponymous 예,하지만 가장 많이 축소 된 형식 만 opcode로 유지됩니다. 예 : 바운드 검사는 코드 경로가 const이기 때문에 빌드시 평가됩니다. 그러나 반환 된 값은 * (data + offset)
v.oddou

16

constexprinline비 정적 변수 (C ++ 17 인라인 변수)를 의미하지 않습니다.

함수를 constexpr암시 하지만 inlineC ++ 17 인라인 변수를 고려할 때 비 정적 변수에는 영향을주지 않습니다.

예를 들어, 내가 게시 한 최소한의 예제를 취한다면 : 인라인 변수는 어떻게 작동합니까? 를 제거 inline하고을 남겨두면 constexpr변수가 여러 주소를 가져옵니다. 이는 인라인 변수가 피하는 주요 사항입니다.

constexpr 그러나 정적 변수는 암시 적으로 정적입니다.

함수 를 constexpr의미 inline하는 최소한의 예

https://stackoverflow.com/a/14391320/895245 에서 언급했듯이 주요 효과는 inline인라인이 아니라 함수의 여러 정의를 허용하는 것입니다. 표준 인용문은 다음과 같습니다. C ++ 헤더 파일에 구현이 포함되는 방법은 무엇입니까?

다음 예제를 통해이를 관찰 할 수 있습니다.

main.cpp

#include <cassert>

#include "notmain.hpp"

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

notmain.hpp

#ifndef NOTMAIN_HPP
#define NOTMAIN_HPP

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

#endif

notmain.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

inline에서 제거 shared_func하면 다음과 같이 링크가 실패합니다.

multiple definition of `shared_func()'

헤더가 여러 .cpp파일에 포함되기 때문 입니다.

우리가 대체하지만 inline함께 constexpr하기 때문에, 그것은 다시 작동 constexpr도 의미한다 inline.

GCC는 ELF 개체 파일에서 심볼을 약한 것으로 표시하여이를 구현합니다. C ++ 헤더 파일에 구현이 어떻게 포함될 수 있습니까?

GCC 8.3.0에서 테스트되었습니다.


3
BTW, 선언 된 정적 클래스 멤버 변수 constexpr는 여전히 인라인입니다. cppreference.com : 선언 된 정적 멤버 변수 (네임 스페이스 범위 변수가 아님) constexpr는 암시 적으로 인라인 변수입니다.
anton_rh

@anton_rh 감사합니다, 그 규칙, 업데이트 답변을 보지 못했습니다.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

open-std.org/JTC1/SC22/WG21/docs/papers/2016/p0386r0.pdf가 말하는 것이 아닙니다 . constexpr은 변수에 대한 인라인을 의미합니다. 클래스 범위의 네임 스페이스 범위 간의 차이에 대한 언급이 없습니다.
v.oddou
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.