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(...) { } }
이 코드는 terminate
C ++ 0x에서 호출 하지만 C ++ 03에서는 호출 되지 않습니다. A::~A
C ++ 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'
언어 특징
- {}를 사용한 균일하고 일반적인 초기화
- 자동
- 협착 방지
- constexpr
- 루프 기반 범위
- nullptr
- 열거 형 클래스
- static_assert
- std :: initializer_list
- Rvalue 참조 (시맨틱 이동)
>>
- 람다
- 다양한 템플릿
- 유형 및 템플릿 별칭
- 유니 코드 문자
- 긴 정수형
- alignas와 alignof
- 선언하다
- 원시 문자열 리터럴
- 일반화 된 포드
- 일반화 된 노동 조합
- 템플릿 인수로서의 로컬 클래스
- 접미 부 리턴 유형 구문
- [[carries_dependency]] 및 [[noreturn]]
- noexcept 지정자
- noexcept 연산자.
- C99 기능 :
- 확장 적분 유형
- 좁은 / 넓은 줄의 연결
- _ _ STDC_HOSTED _ _
- _ 프 래그 마 (X)
- vararg 매크로 및 빈 매크로 인수
- _ _ func _ _
- 인라인 네임 스페이스
- 위임 생성자
- 동급 멤버 이니셜 라이저
- 기본 및 삭제
- 명시 적 변환 연산자
- 사용자 정의 리터럴
- Extern 템플릿
- 함수 템플릿의 기본 템플릿 인수
- 상속 생성자
- 재정의와 최종
- 더 단순하고 일반적인 SFINAE 규칙
- 메모리 모델
- thread_local
표준 라이브러리 구성 요소
- 컨테이너의 initializer_list
- 컨테이너의 시맨틱 이동
- forward_list
- 해시 컨테이너
- unorder_map
- unorder_multimap
- unorder_set
- unorder_multiset
- 자원 관리 포인터
- unique_ptr
- shared_ptr
- weak_ptr
- 동시성 지원
- 실
- 뮤텍스
- 자물쇠
- 조건 변수
- 더 높은 수준의 동시성 지원
- packaged_thread
- 미래
- 약속
- 비동기
- 튜플
- 정규식
- 난수
- uniform_int_distribution
- 정규 분포
- random_engine
- 기타
- int16_t, uint32_t 및 int_fast64_t와 같은 정수 유형 이름
- 정렬
- 예외 복사 및 다시 던지기
- 시스템 오류
- 컨테이너에 대한 emplace () 작업
- constexpr 함수
- noexcept 기능의 체계적인 사용
- 기능과 바인딩
- 문자열을 숫자 값으로 변환
- 범위가 지정된 할당 자
- 유형 특성
- 시간 유틸리티 : 기간 및 time_point
- 비율
- quick_exit
- move (), copy_if () 및 is_sorted ()와 같은 더 많은 알고리즘
- 가비지 콜렉션 ABI
- 원자
더 이상 사용되지 않는 기능
- 소멸자가있는 클래스의 사본 생성자 및 사본 할당 생성
- 문자열 리터럴을 char *에 지정하십시오.
- C ++ 98 예외 사양
- unexcepted_handler
- set_unexpected
- get_unexpected
- 예기치 않은
- 함수 객체 및 관련 함수
- auto_ptr
- 레지스터
- ++ 부울
- 수출
- C 스타일 캐스트
참고 URL : https://stackoverflow.com/questions/6399615/what-breaking-changes-are-introduced-in-c11
'IT story' 카테고리의 다른 글
'POCO'정의 (0) | 2020.04.18 |
---|---|
변수 앞에 더하기 기호의 목적은 무엇입니까? (0) | 2020.04.18 |
"범위 기반 for 루프"에서 작동하도록 사용자 정의 유형을 만드는 방법은 무엇입니까? (0) | 2020.04.18 |
리턴 유형이없는 Java 메소드는 리턴 명령문없이 컴파일 (0) | 2020.04.18 |
GDB에서 '메모리 액세스'에 중단 점을 설정할 수 있습니까? (0) | 2020.04.18 |