Már az ősidőktől kezdve folyik a harc a define-nal és a consttal létrehozott konstansok használata között. Az előbbi egy C örökség, benne a preprocesszálás problémáival, az utóbbi meg túlságosan is új a régivágású C-ről áttért programozóknak. A define mellett szól, hogy aki használja, az pontosan tudja, hogy azt a fordító hogyan fogja felhasználni. Így gyakorlatilag biztos lehet benne, hogy a konstans inline-osodik, és nem történik majd szükségtelen memóriahozzáférés. Valamint a megszokás is ezt a módszert támogatja. A constról viszont azt állítják, hogy szintén inline-osodik, ha tud, bár kötelezően létrejön egy érték is a memóriában, hogy hivatkozásokat és pointereket lehessen rácímezni. Valamint a const képes objektumokat és tömböket is tartalmazni. (A define is, csak annak még korlátozottabb a felhasználási területe.)
Vagyis úgy látszik a constnak nincsenek hátrányai, előnyei azonban annál inkább. És ez a szabvány szerint így is van. De a fordítóprogramgyártók azért ügyeltek arra, hogy ne legyen minden fenékig tejfel. Ugyanis a const tartalma létrejön minden C++ file-ban, amiben szerepel. Tehát ha valaki csinál egy központi headerfile-t, és abba rak bele minden konstanst, akkor bizony keletkezik mindegyikből egy-egy példány forrásonként. Ezeket a példányokat vagy a fordítónak, vagy a linkernek össze kéne vonnia, mint ahogy ezt teszi a string literálokkal is, de mégsem teszi meg. Egyszerűen nem csinálták meg. A Visual Studio és a GCC úgyanúgy bent hagyja több példányban az értékeket. Amíg kicsi a programunk ezzel nincs is semmi baj, de amikor már több száz vagy több ezer forrásunk lesz, és több tucat, vagy akár száz konstansunk, akkor bizony már súlyos gondok lehetnek a program méretével. (Kicsit úgy viselkedik ez a const kulcsszó, mintha static lenne, csak éppen az értékét nem lehet megváltoztatni. Hupsz! A staticról a következő posztban bővebben.)
Lehet a problémán segíteni bizonyos megkötésekkel. Például, ha string konstanst akarunk létrehozni, akkor ne const char *-t vagy const char []-t használjunk, hanem std::stringet. Ekkor ugyanis csak egy üres string objektum jön létre háromszor, és a program inicializálásakor töltődik bele az érték. Mivel a string itt egy string literál, ezért az csak egyszer fog szerepelni a kódban. (Ez a módszer csak Visual Studioban működik, GCC-ben a string továbbra is többször fog szerepelni, mégha beállítjuk a hely optimalizálási opciókat is.) Másik módszer, ami nemcsak stringekre működik, hogy normál változókat használunk, és a header file-ban csak egy extern hivatkozás van rájuk. Ez a módszer azonban még a define-nál is rosszabb.
Akkor egy kis gyakorlat:
const std::string s = "Hello!";
const char c[] = "Haliho!";
const int a = 0x12345678;
#include <iostream>
És csináljunk még két forrást f2 és f3 függvényekkel, amik pontosan ugyanígy néznek ki a nevükön kívül. Ha meghívjuk őket, látni fogjuk, hogy minden cím különbözik. A kódban egy darab Hello! lesz, valamint 3 darab Haliho! es 3 db 0x12345678.
#include <iomanip>
#include "header.h"
void f1()
{
std::cout << "Address of s:" << std::hex << &s << " Address of c:" << reinterpret_cast<void*>(c) << " Address of a:" << &a << std::endl;
}
Ez a probléma kizárólag azokat a constokat érinti, amik header file-okban vannak. És a igazából akkor okoz csak gondot, ha a projektünk elég nagy, vagy nagyon kevés helyünk van, mint mondjuk egy beágyazott rendszernél vagy telefonnál. Tehát ezekben az esetekben jobb, ha header file-okban define-t használunk const helyett, mert pillanatnyilag ez a legjobb megoldás. Legalábbis, amíg a fórdítógyártók észhez nem térnek.