web-dev-qa-db-fra.com

Quelles modifications introduites dans C ++ 14 peuvent potentiellement casser un programme écrit en C ++ 11?

Introduction

Avec le C++ 14 (c'est-à-dire C++ 1y) Standard dans un état proche d'être définitif, les programmeurs doivent s'interroger sur la compatibilité ascendante, et questions liées à ces.


La question

Dans les réponses de cette question , il est indiqué que la norme comporte un annexe dédié aux informations concernant les modifications entre révisions.

Il serait utile d’expliquer ces problèmes potentiels dans le Annexe mentionné précédemment, peut-être à l’aide de documents officiels se rapportant à ce qui est mentionné ici.

  • Selon le standard: Quels changements introduits dans C++ 14 peuvent potentiellement casser un programme écrit en C++ 11?
58

Remarque : Dans cet article, je considère un "changement de changement" comme étant l'un des, ou les deux,;
 1. un changement qui rendra légal C++ 11 mal formé lorsque compilé en tant que C++ 14, et;
2. une modification qui modifiera le comportement de l'exécution à la compilation C++ 14, vs C++ 11.


C++ 11 vs C++ 14, que dit la norme?

Le projet de norme ( n3797 ) comporte une section dédiée à ce type d’informations, dans laquelle elle décrit les différences (potentiellement décisives) entre une révision de la norme et une autre.

Ce message a utilisé cette section, [diff.cpp11], en tant que base d’une discussion semi-élaborée sur les modifications susceptibles d’affecter le code écrit pour C++ 11, mais compilé sous la forme C++ 14.


C.3.1] Séparateurs de chiffres

Le séparateur de chiffres a été introduit afin que l’on puisse, d’une manière plus lisible, écrire des littéraux numériques et les séparer de manière plus naturelle.

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

Il est facile de voir que (2) est beaucoup plus facile à lire que (1) dans le fragment de code ci-dessus, alors que les deux initialiseurs ont la même valeur.

Le problème potentiel concernant cette fonctionnalité est que single-quote désignait toujours le début/la fin d'un caractère-littéral dans C++ 11, mais dans C++ 14 un single-quote peut entourer un caractère-littéral, ou être utilisé de la manière indiquée précédemment (2).


Exemple d’extrait de code, légal à la fois C++ 11 et C++ 14, mais avec un comportement différent.

#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 }`

(Remarque: vous trouverez plus d'informations sur single-quotes sous forme de séparateurs de chiffres dans n3781.pdf )


C.3.2] Désallocation de taille

C++ 14 introduit la possibilité de déclarer une surcharge globale de operator delete approprié pour taille de localisation, ce qui n’était pas possible dans C++ 11.

Toutefois, la norme stipule également qu'un développeur ne peut déclarer qu'une seule des fonctions liées ci-dessous. Il doit déclarer soit aucune , soit les deux ; qui est indiqué dans [new.delete.single] p11.

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


Informations supplémentaires sur le problème potentiel:

Les programmes existants qui redéfinissent la version globale non dimensionnée ne définissent pas également la version dimensionnée. Lorsqu'une implémentation introduit une version dimensionnée, le remplacement est incomplet et il est probable que les programmes appellent le désallocateur dimensionné fourni par l'implémentation sur les objets alloués avec l'allocateur fourni par le programmeur.

Remarque : Citation extraite de n3536 - Dislocation au format C++

(Remarque: Plus d’intérêt est disponible dans l’article intitulé n3536 - Dislocation au format C++ , écrit par Lawrence Crowl)


C.3.3] constexpr fonctions-membres, plus implicitement const

Il y a beaucoup de changements dans constexpr en C++ 14, mais c'est le seul changement qui changera la sémantique entre C++ 11 et C++ 14 est la constante d'un fonction-membre marquée comme constexpr.

La raison derrière ce changement est de permettre à constexprfonctions-membres de muter l'objet auquel ils appartiennent, ce qui est autorisé en raison de la relaxation de - constexpr .

struct A { constexpr int func (); };

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


Matériau recommandé pour ce changement et pourquoi il est suffisamment important pour introduire un risque de casse de code:


Exemple d’extrait de code, légal à la fois C++ 11 et C++ 14, mais avec un comportement différent

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] Suppression de std::gets

std::gets a été supprimé de la bibliothèque standard car considéré comme dangereux .

Les implications de ceci sont bien sûr qu'essayer de compiler le code écrit pour C++ 11, en C++ 14, où une telle fonction est utilisée, échouera probablement à la compilation.


(Remarque: il existe des façons d'écrire code qui ne manque pas de compiler et qui a un comportement différent, cela dépend de la suppression de std::gets de la Bibliothèque standard)

229