c++11constexpr 사용 시 발생하는 구덩이 상세 정보

최근에 constexpr을 사용할 때 무심결에 작은 구덩이를 밟았다.
다음 예제는 다음과 같습니다.

#include <iostream>

constexpr int n = 10;
constexpr char *msg = "Hello, world!";

int main()
{
    for (auto i = 0; i < n; ++i) {
        std::cout << msg << std::endl;
    }
}

constexpr은 모두에게 익숙한 것일 뿐만 아니라, 가장 자주 사용하는 c++11의 새로운 특성 중의 하나이기도 하다.매크로에 비해 더 강한 유형의 안전을 제외하고constexpr는 컴파일러 계산을 가져왔다.
위의 코드는 상당히 간단합니다. "Hello, world!"를 순환 출력합니다.이 문자열은 10번입니다.
이렇게 간단한 코드에 대해 토론할 필요가 있습니까?처음에 나도 이렇게 생각했지만, 우리가 컴파일해서 실행할 때 다음과 같은 경고를 받게 된다.

$ g++ --version
                      
g++ (GCC) 10.2.0
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


$ g++ -std=c++17 -Wall -Wextra test.cpp

test.cpp:4:23:  : ISO C++ forbids converting a string constant to ‘char*' [-Wwrite-strings]
    4 | constexpr char *msg = "Hello, world!";
      |                       ^~~~~~~~~~~~~~~

이 정보는 c++가char*에 문자열 글자의 값을 부여하는 것을 허락하지 않는다는 것을 의미합니다.
하지만constexpr에 대해선문서
A constexpr specifier used in an object declaration implies const.
여기의object는 변수로 이해할 수 있습니다. 이것은 constexpr가 수식한 변수는 은밀하게 const 한정자를 추가한다는 뜻입니다.
즉,

// T  
constexpr T a = xxx;
//  , :
T const a = xxx;
우리가 있는 이곳의 T는 실제로 지침을 포함하여 임의의 유형을 채울 수 있다.이것은 우리의 바늘 변수에 const가 있다는 것을 설명하는 것이 아닙니까?
눈치 빠른 독자들은 아마도 답을 알고 있을 것이다. constexpr에 추가된 것은 맨 윗부분의 const이다.
그래서 우리의 코드는 실제로 이렇다.

//  
constexpr char *msg = "Hello, world!";
//  
char * const msg = "Hello, world!";
다음 줄의 msg는 실제적으로char를 가리키는 바늘 상수이며, 우리는 그것을 통해 가리키는 문자열을 임의로 수정할 수 있다. (물론 이것은 정의되지 않은 행위이다.)바늘 상량은 우리가 이 바늘을 다른 대상을 다시 가리킬 수 없다는 것을 의미한다. 이const는 바늘 자체에 작용하기 때문에 맨 윗부분const라고 부른다.
한편, 문자열 상수의 유형은constchar[N]입니다. 표현식에서constchar*로 퇴화됩니다. 이것은 상수 문자열을 가리키는 바늘을 나타냅니다. 여기의const의 밑바닥은 우리의 바늘 자체가 아니라 가리키는 대상에 작용하기 때문입니다.
맨 윗부분const에 대해 값을 부여할 때 제거할 수 있지만 밑부분const는 안 됩니다. 이것이 컴파일러가 경고를 보내는 이유입니다.
정확한 방법도 간단합니다. constexpr은 const의 등가 대체품이 아닙니다. 맨 윗부분만 추가할 뿐 밑부분만 추가할 수 있습니다.
그래서 constexpr의 문자열 상수는 이렇게 써야 합니다.

constexpr const char *p = "Hello, world!";
또는 당신의 컴파일 환경은 c++17을 지원합니다. 저는 당신이 이렇게 쓰는 것을 추천합니다.

#include <string_view>

constexpr std::string_view msg = "Hello, world!";

string_ 사용view 이후에는 위의 맨 윗층/밑층const의 구덩이가 나타나지 않습니다.그래서 현대 c++에서는 나체 바늘을 사용하지 않아도 되도록 사용하지 않는다.
참고
https://stackoverflow.com/questions/54258241/warning-iso-c-forbids-converting-a-string-constant-to-char-for-a-static-c
총결산
c++11 constexpr를 사용할 때 구덩이를 만났을 때 이 글을 소개합니다. 더 많은 c++ 11 constexpr 구덩이 내용은 저희 이전의 글을 검색하거나 아래의 관련 글을 계속 훑어보십시오. 앞으로 많은 응원 부탁드립니다!

좋은 웹페이지 즐겨찾기