IT story

C ++ 11에 도입 된 주요 변경 사항은 무엇입니까?

hot-time 2020. 4. 18. 09:38
반응형

C ++ 11에 도입 된 주요 변경 사항은 무엇입니까?


나는 오래된 코드가 컴파일을 멈추게하는 C ++ 11의 적어도 하나의 변경 사항 : explicit operator bool()표준 라이브러리에 도입 하여의 이전 인스턴스를 대체 한다는 것을 알고 있습니다 operator void*(). 물론, 이것이 깨질 코드는 아마도 처음에는 유효하지 않은 코드 일 것입니다. 그럼에도 불구하고 여전히 중요한 변화입니다. 더 이상 유효하지 않은 프로그램은 더 이상 유효하지 않습니다.

다른 주요 변경 사항이 있습니까?


FDIS에는 부록 C.2"C ++ 및 ISO C ++ 2003" 에 비 호환성 섹션이 있습니다.

여기에 FDIS를 해석하여 SO 답변으로 적합하게 만들기 위해 요약합니다. 차이점을 설명하기 위해 내 예제를 추가했습니다.

라이브러리 관련 비 호환성이 몇 가지 있지만 그 의미를 정확히 알지 못하므로 다른 사람들이 자세히 설명 할 수 있습니다.

핵심 언어


#define u8 "abc"
const char *s = u8"def"; // Previously "abcdef", now "def"

#define _x "there"
"hello"_x // now a user-defined-string-literal. Previously, expanded _x .

새 키워드 : alignas, alignof, char16_t, char32_t, constexpr, decltype, noexcept, nullptr, static_assert 및 thread_local


long으로 표현할 수있는 것보다 큰 특정 정수 리터럴은 부호없는 정수 유형에서 부호있는 long long으로 변경 될 수 있습니다.


정수 나누기를 사용하는 유효한 C ++ 2003 코드는 결과를 0 또는 음의 무한대로 반올림하지만 C ++ 0x는 항상 결과를 0으로 반올림합니다.

(실제로 대부분의 사람들에게 호환성 문제는 아닙니다).


키워드 auto를 스토리지 클래스 지정자로 사용하는 유효한 C ++ 2003 코드 는 C ++ 0x에서 유효하지 않을 수 있습니다.


축소 변환은 C ++ 03과 호환되지 않습니다. 예를 들어 다음 코드는 C ++ 2003에서는 유효하지만 double to int는 축소 변환이므로이 국제 표준에서는 유효하지 않습니다.

int x[] = { 2.0 };

암시 적으로 선언 된 특수 멤버 함수는 암시 적 정의의 형식이 잘못되었을 때 삭제 된 것으로 정의됩니다.

정의가 필요하지 않은 상황 (예 : 잠재적으로 평가되지 않은 설명)에서 이러한 특수 멤버 함수 중 하나를 사용하는 유효한 C ++ 2003 프로그램은 잘못 구성됩니다.

나에 의한 예 :

struct A { private: A(); };
struct B : A { };
int main() { sizeof B(); /* valid in C++03, invalid in C++0x */ }

이러한 크기의 트릭은 일부 SFINAE에서 사용되었으며 지금 변경해야합니다. :)


사용자 선언 소멸자는 암시 적 예외 사양이 있습니다.

나에 의한 예 :

struct A {
  ~A() { throw "foo"; }
};

int main() { try { A a; } catch(...) { } }

이 코드는 terminateC ++ 0x에서 호출 하지만 C ++ 03에서는 호출 되지 않습니다. A::~AC ++ 0x에서 의 암시 적 예외 사양은 입니다 noexcept(true).


포함 된 유효한 C ++ 2003 선언 export이 C ++ 0x에서 잘못 구성되었습니다.


유효한 C ++ 2003 표현식 >뒤에 바로 다른 표현식이 포함 되어 >이제는 두 개의 템플리트를 닫는 것으로 간주 될 수 있습니다.

C ++ 03에서는 >>항상 시프트 연산자 토큰이됩니다.


내부 연결로 함수의 종속 호출을 허용합니다.

나에 의한 예 :

static void f(int) { }
void f(long) { }

template<typename T>
void g(T t) { f(t); }

int main() { g(0); }

C ++ 03에서는을 호출 f(long)하지만 C ++ 0x에서는을 호출합니다 f(int). C ++ 03 및 C ++ 0x에서 다음 호출이 있습니다 f(B)(인스턴스화 컨텍스트는 여전히 extern linkage 선언 만 고려합니다).

struct B { };
struct A : B { };

template<typename T>
void g(T t) { f(t); }

static void f(A) { }
void f(B) { }

int main() { A a; g(a); }

f(A)외부 연결이 없기 때문에 더 나은 일치 가 이루어지지 않습니다.


라이브러리 변경

C ++ 0x의 C ++ 표준 라이브러리에 추가 된 식별자를 사용하는 유효한 C ++ 2003 코드는이 국제 표준에서 컴파일 또는 다른 결과를 생성하지 못할 수 있습니다.


#includes새로운 C ++ 0x 표준 라이브러리 헤더의 이름을 가진 헤더가이 국제 표준에서 유효하지 않은 유효한 C ++ 2003 코드 .


스왑이있을 것으로 예상되어 컴파일 된 유효한 C ++ 2003 코드는 <algorithm>다음을 포함해야합니다.<utility>


글로벌 네임 스페이스 posix는 이제 표준화를 위해 예약되어 있습니다.


유효한 C ++가 정의하는 것이 2003 코드 override, final, carries_dependency, 또는 noreturn매크로와 같은 C ++ 0X에 유효하지 않습니다.


자동 키워드의 의미가 변경되었습니다.


변화를 깨고?

당신이 사용하는 경우 음, 한 가지, decltype, constexpr, nullptr, 등의 식별자로 당신은 문제가 될 수 있습니다 ...


비 호환성 섹션에서 다루지 않는 일부 핵심 비 호환성 :


C ++ 0x는 이름이 템플리트 템플리트 매개 변수에 인수로 전달되는 경우 주입 된 클래스 이름을 템플리트로 처리하고 템플리트 유형 매개 변수에 전달되는 경우 유형으로 처리합니다.

이 시나리오에서 삽입 된 클래스 이름을 항상 유형으로 사용하는 경우 유효한 C ++ 03 코드가 다르게 작동 할 수 있습니다. 내 clang PR에서 가져온 예제 코드

template<template<typename> class X>
struct M { };

template<template<typename> class X>
void g(int = 0); // #1

template<typename T>
void g(long = 0); // #2

template<typename T>
struct A {
  void f() {
    g<A>(); /* is ambiguous in C++0x */
    g<A>(1); /* should choose #1 in C++0x */
  }
};

void h() {
  A<int> a;
  a.f();
}

C ++ 03에서 코드는 두 번째를 g두 번 호출합니다 .


C ++ 0x는 C ++ 03에 종속 된 일부 이름을 이제 비 종속으로 만듭니다. 또한 인스턴스화시 반복 될 현재 클래스 템플릿의 멤버를 참조하는 비 의존적 정규화 된 이름에 대한 이름 조회가 필요하며 이러한 이름이 템플릿 정의 컨텍스트에서 수행 된 것과 동일한 방식으로 조회되는지 확인해야합니다.

우위 규칙에 의존하는 유효한 C ++ 03 코드는 이제이 변경으로 인해 더 이상 컴파일되지 않을 수 있습니다.

예:

struct B { void f(); };

template<typename T>
struct A : virtual B { void f(); };

template<typename T>
struct C : virtual B, A<T> {
  void g() { this->f(); }
};

int main() { C<int> c; c.g(); }

이 유효한 C ++ 03 코드 A<int>::f는 C ++ 0x에서 유효하지 않습니다. 인스턴스화 할 때 이름 조회가 A<int>::f와 반대로 발견 되어 B::f정의 조회와 충돌이 발생하기 때문입니다.

이 시점에서 이것이 FDIS의 결함인지는 확실하지 않습니다. 위원회는이를 알고 있으며 상황을 평가할 것입니다.


마지막 부분이 기본 클래스를 나타내는 규정 된 이름의 규정 자의 마지막 부분에있는 식별자와 동일한 사용 선언은 선언을 사용하여 해당 이름의 멤버 대신 생성자의 이름을 지정합니다.

예:

struct A { protected: int B; };
typedef A B;

struct C : B {
  // inheriting constructor, instead of bringing A::B into scope
  using B::B;
};

int main() { C c; c.B = 0; }

위의 예제 코드는 C ++ 03에서는 잘 구성되어 있지만 C ++ 0x에서는 잘못 구성 A::B되어 main있습니다.


스트림 추출 실패는 다르게 처리됩니다.

#include <sstream>
#include <cassert>

int main()
{
   std::stringstream ss;
   ss << '!';

   int x = -1;

   assert(!(ss >> x)); // C++03 and C++11
   assert(x == -1);    // C++03
   assert(x == 0);     // C++11
}

제안 변경

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3246.html#23

표준 참조

[C++03: 22.2.2.1.2/11]: 2 단계 처리 결과는 다음 중 하나 일 수 있습니다.

  • 2 단계에서 일련의 문자가 누적되어 (의 규칙에 따라 scanf) 유형의 값으로 변환 val됩니다. 이 값은에 저장 val되고 ios_base::goodbit에 저장됩니다 err.
  • 2 단계에서 누적 된 문자 순서로 인해 scanf입력 오류가보고되었을 수 있습니다. ios_base::failbit에 할당되어 err있습니다. [ed :에 저장된 것이 없습니다 val.]

[C++11: 22.4.2.1.2/3]: [..] 저장할 숫자 값은 다음 중 하나 일 수 있습니다.

  • 변환 함수가 전체 필드를 변환하지 못하면 0입니다 . ios_base::failbit에 할당되어 err있습니다.
  • 필드 값이 너무 큰 양성을 나타내는 경우 가장 긍정적 표현할 값은로 표현된다 val. ios_base::failbit에 할당되어 err있습니다.
  • 필드가로 표현하기에 너무 큰 음수를 나타내는 경우 부호가없는 정수 유형에 대해 가장 음의 표현 가능한 값 또는 0입니다 val. ios_base::failbit에 할당되어 err있습니다.
  • 그렇지 않으면 변환 된 값

결과 숫자 값은에 저장됩니다 val.

구현

  • C ++ 11에 대해 GCC 4.8이 올바르게 출력됩니다 .

    어설 션`x == -1 '실패

  • C ++ 03에 대한 GCC 4.5-4.8 모든 결과 는 다음과 같습니다. 버그로 보입니다.

    어설 션`x == -1 '실패

  • C ++ 03에 대해 Visual C ++ 2008 Express가 올바르게 출력됩니다.

    어설 션 실패 : x == 0

  • Visual C ++ 2012 Express 가 C ++ 11에 대해 잘못 출력되어 구현 상태 문제인 것으로 보입니다.

    어설 션 실패 : x == 0


명시 적 변환 연산자의 도입은 어떻게 중대한 변화입니까? 이전 버전은 여전히 ​​이전과 마찬가지로 "유효"합니다.

예에서에서 operator void*() const로의 변경은 explicit operator bool() const중대한 변경이 될 수 있지만 자체적으로 잘못된 방식으로 사용되는 경우에만 가능합니다. 적합한 코드는 깨지지 않습니다.

이제 또 다른 주요 변경 사항은 집계 초기화 중에 축소 변환을 금지하는 것입니다 .

int a[] = { 1.0 }; // error

편집 : 기억하기 만하면 std::identity<T>C ++ 0x에서 제거됩니다 (주 참조). 유형을 종속시키는 편리한 구조체입니다. 구조체는 실제로 많은 일을하지 않기 때문에 수정해야합니다.

template<class T>
struct identity{
  typedef T type;
};

더 효율적인 코드를 허용하지만 몇 가지 경우에 대해 이전 버전과의 호환성을 자동으로 깨뜨리는 컨테이너 라이브러리에는 수많은 변경 사항이 있습니다.

예를 들어, std::vector기본 구성, C ++ 0x 및 주요 변경 사항을 고려하십시오 .


이전 버전과의 호환성을 깨는 암시 적 이동 에 대한 많은 토론이있었습니다.

( 관련 토론이있는 오래된 페이지 )

주석을 읽으면 암시 적 이동 리턴도 주요 변경 사항입니다.


struct x {
   x(int) {}
};

void f(auto x = 3) { }

int main() {
   f();
}

C ++ 03 : 유효합니다.

C ++ 0x : error: parameter declared 'auto'


언어 특징

  1. {}를 사용한 균일하고 일반적인 초기화
  2. 자동
  3. 협착 방지
  4. constexpr
  5. 루프 기반 범위
  6. nullptr
  7. 열거 형 클래스
  8. static_assert
  9. std :: initializer_list
  10. Rvalue 참조 (시맨틱 이동)
  11. >>
  12. 람다
  13. 다양한 템플릿
  14. 유형 및 템플릿 별칭
  15. 유니 코드 문자
  16. 긴 정수형
  17. alignas와 alignof
  18. 선언하다
  19. 원시 문자열 리터럴
  20. 일반화 된 포드
  21. 일반화 된 노동 조합
  22. 템플릿 인수로서의 로컬 클래스
  23. 접미 부 리턴 유형 구문
  24. [[carries_dependency]] 및 [[noreturn]]
  25. noexcept 지정자
  26. noexcept 연산자.
  27. C99 기능 :
    • 확장 적분 유형
    • 좁은 / 넓은 줄의 연결
    • _ _ STDC_HOSTED _ _
    • _ 프 래그 마 (X)
    • vararg 매크로 및 빈 매크로 인수
  28. _ _ func _ _
  29. 인라인 네임 스페이스
  30. 위임 생성자
  31. 동급 멤버 이니셜 라이저
  32. 기본 및 삭제
  33. 명시 적 변환 연산자
  34. 사용자 정의 리터럴
  35. Extern 템플릿
  36. 함수 템플릿의 기본 템플릿 인수
  37. 상속 생성자
  38. 재정의와 최종
  39. 더 단순하고 일반적인 SFINAE 규칙
  40. 메모리 모델
  41. thread_local

표준 라이브러리 구성 요소

  1. 컨테이너의 initializer_list
  2. 컨테이너의 시맨틱 이동
  3. forward_list
  4. 해시 컨테이너
    • unorder_map
    • unorder_multimap
    • unorder_set
    • unorder_multiset
  5. 자원 관리 포인터
    • unique_ptr
    • shared_ptr
    • weak_ptr
  6. 동시성 지원
    • 뮤텍스
    • 자물쇠
    • 조건 변수
  7. 더 높은 수준의 동시성 지원
    • packaged_thread
    • 미래
    • 약속
    • 비동기
  8. 튜플
  9. 정규식
  10. 난수
    • uniform_int_distribution
    • 정규 분포
    • random_engine
    • 기타
  11. int16_t, uint32_t 및 int_fast64_t와 같은 정수 유형 이름
  12. 정렬
  13. 예외 복사 및 다시 던지기
  14. 시스템 오류
  15. 컨테이너에 대한 emplace () 작업
  16. constexpr 함수
  17. noexcept 기능의 체계적인 사용
  18. 기능과 바인딩
  19. 문자열을 숫자 값으로 변환
  20. 범위가 지정된 할당 자
  21. 유형 특성
  22. 시간 유틸리티 : 기간 및 time_point
  23. 비율
  24. quick_exit
  25. move (), copy_if () 및 is_sorted ()와 같은 더 많은 알고리즘
  26. 가비지 콜렉션 ABI
  27. 원자

더 이상 사용되지 않는 기능

  1. 소멸자가있는 클래스의 사본 생성자 및 사본 할당 생성
  2. 문자열 리터럴을 char *에 지정하십시오.
  3. C ++ 98 예외 사양
    • unexcepted_handler
    • set_unexpected
    • get_unexpected
    • 예기치 않은
  4. 함수 객체 및 관련 함수
  5. auto_ptr
  6. 레지스터
  7. ++ 부울
  8. 수출
  9. C 스타일 캐스트

참고 URL : https://stackoverflow.com/questions/6399615/what-breaking-changes-are-introduced-in-c11

반응형