HTML

C++ programozás

Főként C++ programozásról, de lehet szó még C#, D vagy más nyelvről is.

Friss topikok

  • tormanator: A CG-shaderben megírt raytracing 106x gyorsabb, mint egy SSE-utaításokkal futó raytracing. Mindeg... (2011.09.08. 07:00) Csak párhuzamosan!
  • koszperv: @Vorbis: Szia! Köszöntlek, mint a blogom első hozzászólóját. Az enum egyébként tényleg egész haszn... (2009.12.30. 11:44) const vs define

Linkblog

2009.12.26. 13:46 koszperv

const vs define

Címkék: konstans constant const define #define

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>
#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;
}
É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.

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.

 

 

3 komment

A bejegyzés trackback címe:

https://progcpp.blog.hu/api/trackback/id/tr931624024

Kommentek:

A hozzászólások a vonatkozó jogszabályok  értelmében felhasználói tartalomnak minősülnek, értük a szolgáltatás technikai  üzemeltetője semmilyen felelősséget nem vállal, azokat nem ellenőrzi. Kifogás esetén forduljon a blog szerkesztőjéhez. Részletek a  Felhasználási feltételekben és az adatvédelmi tájékoztatóban.

Vorbis 2009.12.29. 13:39:51

Hali!

Én inkább az enum-okat ajánlanám. Egyrészt garantáltan mindenütt csak mint érték fog szerepelni, másrészt nem kell velük a global namespace-t szennyezni (ez szörnyű az enum-okban).

Vorbis 2009.12.29. 13:40:30

izé, márminthogy szörnyű a define-ban...

koszperv 2009.12.30. 11:44:43

@Vorbis: Szia! Köszöntlek, mint a blogom első hozzászólóját.
Az enum egyébként tényleg egész használható ötlet, csak sajnos elég erős megszorításokkal. Ugyanis enumban kizárólag enumerálható érték, vagyis egészszám szerepelhet. Se lebegőpontos szám, se string, nem is beszélve az egyébb objektumokról, amiket constként létre tudunk hozni. Van egy másik kisebb megszorítása is: az, hogy nem lehet rá referenciát vagy pointert kérni. De ez utóbbi általában nem gond.
süti beállítások módosítása