Какие изменения, внесенные в C++14, потенциально могут сломать программу, написанную на C++11?


введение

с C++14 (ака. C++1y) стандарт в состоянии, близком к окончательному, программисты должны спросить себя о обратной совместимости и проблемах, связанных с такими.


вопрос

в ответах на этот вопрос говорится, что стандарт имеет приложение посвящен информации об изменениях между переделки.

было бы полезно, если бы эти потенциальные проблемы в ранее упомянутых приложение можно было бы объяснить, возможно, с помощью каких-либо официальных документов, связанных с тем, что там упоминается.

  • согласно стандарту: какие изменения внесены в C++14 потенциально может нарушить программу, написанную на C++11?
1 58

1 ответ:

Примечание: в этом посте я рассматриваю "breaking change " быть либо тем, либо другим;
1. a change that will make legal C++11 ill-formed when compiled as C++14, and;
2. изменение, которое изменит поведение среды выполнения при компиляции как C++14, vs C++11.


C++11 vs C++14, что говорит стандарт?

стандартный проект ( n3797) имеет a раздел, посвященный именно этому виду информации, где описываются (потенциально нарушающие) различия между одной редакцией стандарта и другой.

этот пост использовал этот раздел,[diff.cpp11], в качестве основы для полу-детального обсуждения изменений, которые могут повлиять на код, написанный для C++11, но собран как C++14.


C. 3. 1] Разделители Цифр

был введен разделитель цифр чтобы можно было более читаемым образом писать числовые литералы и разделять их более естественным образом.

int x = 10000000;   // (1)
int y = 10'000'000; // (2), C++14

это легко увидеть (2) гораздо легче читать, чем (1) в приведенном выше фрагменте кода, в то время как оба инициализатора имеют одинаковое значение.

потенциальная проблема в отношении этой функции заключается в том, что одиночная кавычка всегда обозначает начало / конец a символ-литерал на C++11, но в C++14 a одиночная кавычка может быть, окружающие символ-литерал, или используется в ранее показанном виде (2).


пример фрагмента, законный в обоих C++11 и C++14, но с разным поведением.

#define M(x, ...) __VA_ARGS__

int a[] = { M(1'2, 3'4, 5) };

// int a[] = { 5 };        <-- C++11
// int a[] = { 3'4, 5 };   <-- C++14
//                              ^-- semantically equivalent to `{ 34, 5 }`

(Примечание: дополнительная информация о одиночные кавычки как разделители цифр можно найти в n3781.pdf)


C. 3. 2] Размерное Освобождение

C++14 вводит возможность объявить глобальную перегрузку operator delete подходит для размера освобождения, что-то, что не было возможно в C++11.

однако стандарт также требует, чтобы разработчик не мог объявить только один из двух связанных функции ниже, он должен объявить либо нет или и; что говорится в [new.удалить.single]p11.

void operator delete (void*) noexcept;
void operator delete (void*, std::size_t) noexcept; // sized deallocation


дополнительная информация о потенциальной проблеме:

существующие программы, которые переопределяют глобальную версию без размера, также не делают определите размер версии. Когда реализация вводит размер версия, замена была бы неполный и вполне вероятно, что программы вызвали бы реализацию-обеспеченный размерный деаллокатор на объекты, выделенные с помощью программируемого распределителя.

Примечание: цитата взята из n3536 - C++ для размера изъятия

(Примечание: больше интересного можно найти в статье под названием n3536 - C++ для размера изъятия, написано Корячусь Лоуренс )


С. 3.3] constexpr функции-члены, больше неявно const

есть много изменений к constexpr в C++14, но единственное изменение, которое изменит семантику между C++11 и C++14 - это constantness на член-функцию обозначено как constexpr.

обоснование этого изменения заключается в том, чтобы позволить constexpr член-функции мутировать объект, к которому они принадлежат, то, что разрешено из-за релаксация constexpr.

struct A { constexpr int func (); };

// struct A { constexpr int func () const; }; <-- C++11
// struct A { constexpr int func ();       }; <-- C++14


рекомендуемый материал по этому изменению, и почему это достаточно важно, чтобы ввести потенциальный код поломки:


пример фрагмента, законный в обоих C++11 и C++14, но с разными поведение

struct Obj {
  constexpr int func (int) {
    return 1;
  }

  constexpr int func (float) const {
    return 2;
  }
};

Obj const a = {}; 
int const x = a.func (123);

// int const x = 1;   <-- C++11
// int const x = 2;   <-- C++14

C. 3. 4] Удаление std::gets

std::gets была удалены из стандартной библиотеки, потому что это считается опасным.

последствия этого, конечно, что попытка скомпилировать код, написанный для C++11, в C++14, где используется такая функция, скорее всего, просто не удастся компилировать.


(Примечание: есть способы написания код что не удается скомпилировать, и имеют различное поведение, которое зависит от удаления std::gets С Стандартная Библиотека)