Section 9.4.2, les données membres Statiques, de la norme C++ états:
Si un static
membre de données est de const
intégrale ou const
type d'énumération, sa déclaration dans la définition de classe peut spécifier un const-initialiseur qui doit être une expression constante.
Par conséquent, il est possible que la valeur d'une donnée membre statique pour être inclus "dans la classe" (par qui je présume que tu veux dire dans la déclaration de la classe). Cependant, le type de la donnée membre statique doit être un const
intégrale ou const
de type énumération. La raison pour laquelle les valeurs des données membres statiques d'autres types de ne peut pas être spécifié dans la déclaration de classe, c'est que non-trivial d'initialisation est probablement nécessaire (c'est à dire, un constructeur a besoin pour fonctionner).
Imaginez si les conditions suivantes étaient légales:
// my_class.hpp
#include <string>
class my_class
{
public:
static std::string str = "static std::string";
//...
Chaque fichier de l'objet correspondant au RPC fichiers qui incluent cet en-tête ne serait pas seulement d'avoir une copie de l'espace de stockage pour my_class::str
(composé de l' sizeof(std::string)
octets), mais aussi un "ctor section" qui appelle l' std::string
constructeur prenant un C-string. Chaque copie de l'espace de stockage pour my_class::str
seront identifiés par un label commun, donc un linker pourrait théoriquement fusionner toutes les copies de l'espace de stockage en un seul. Cependant, un éditeur de liens ne seraient pas en mesure d'isoler toutes les copies du constructeur de code dans les fichiers de l'objet' ctor sections. Ce serait comme demander à l'éditeur de liens pour supprimer tout le code pour initialiser str
dans la compilation des éléments suivants:
std::map<std::string, std::string> map;
std::vector<int> vec;
std::string str = "test";
int c = 99;
my_class mc;
std::string str2 = "test2";
EDIT Il est instructif de regarder l'assembleur de sortie de g++ pour le code suivant:
// SO4547660.cpp
#include <string>
class my_class
{
public:
static std::string str;
};
std::string my_class::str = "static std::string";
L'assemblée de code peut être obtenue en exécutant:
g++ -S SO4547660.cpp
En regardant à travers l' SO4547660.s
le fichier que g++ génère, vous pouvez voir qu'il y a beaucoup de code pour un si petit fichier source.
__ZN8my_class3strE
est l'étiquette de l'espace de stockage pour my_class::str
. Il y a aussi le montage d'une source de __static_initialization_and_destruction_0(int, int)
la fonction, qui a l'étiquette __Z41__static_initialization_and_destruction_0ii
. Cette fonction est spécifique à g++, mais sachez juste que g++ sera assurez-vous qu'elle est appelée avant tout non-initialiseur de code est exécuté. Notez que la mise en œuvre de cette fonction appelle __ZNSsC1EPKcRKSaIcE
. C'est la déformation symbole std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&)
.
Revenons à l'exemple hypothétique ci-dessus et à l'aide de ces informations, chaque fichier de l'objet correspondant à un fichier CPP qui inclut my_class.hpp
aurait l'étiquette
__ZN8my_class3strE
pour sizeof(std::string)
octets ainsi que de l'assemblée du code pour appeler l' __ZNSsC1EPKcRKSaIcE
dans sa mise en œuvre de l' __static_initialization_and_destruction_0(int, int)
fonction. L'éditeur de liens peut facilement fusionner toutes les occurrences de __ZN8my_class3strE
, mais il ne peut pas isoler le code qui appelle __ZNSsC1EPKcRKSaIcE
dans le fichier de l'objet de la mise en œuvre de l' __static_initialization_and_destruction_0(int, int)
.