/ Forside / Teknologi / Udvikling / C/C++ / Nyhedsindlæg
Login
Glemt dit kodeord?
Brugernavn

Kodeord


Reklame
Top 10 brugere
C/C++
#NavnPoint
BertelBra.. 2425
pmbruun 695
Master_of.. 501
jdjespers.. 500
kyllekylle 500
Bech_bb 500
scootergr.. 300
gibson 300
molokyle 287
10  strarup 270
Uklarhed mht. smart pointers
Fra : Mark


Dato : 25-12-03 18:24

Hej NG

Jeg har et lille syntaks spørgsmål til følgende kode:

template <class T> class auto_ptr
{
T* ptr;
public:
explicit auto_ptr(T* p = 0) : ptr(p) {}
~auto_ptr() {delete ptr;}
T& operator*() {return *ptr;}
T* operator->() {return ptr;}
// ...
};

Det der undrer er linjen: explicit auto_ptr(T* p = 0) : ptr(p) {}
Hvad gør ':' den har jeg ellers kun set i en constructor i forbindelse
med nedarvning. Såvidt jeg kan se nedarver auto_ptr ikke fra ptr?!

Er der nogle der kan kaste lidt lys over dette?!

Med venlig hilsen
Mark


 
 
Mogens Hansen (25-12-2003)
Kommentar
Fra : Mogens Hansen


Dato : 25-12-03 19:15


"Mark" <no@email.dk> wrote:

[8<8<8<]
> Er der nogle der kan kaste lidt lys over dette?!

Det er initializer listen.

Mellem ':' og '{' står hvordan basis-klasse og data-medlemmer bliver
initialiseret.
For begge dele gælder at hvis der ikke står noget vil default constructoren
blive brugt til at initialisere den pågældende del med.
Hvis en given del (hvad enten det er en basis-klasse eller et data-medlem)
ikke har nogen default constructor er man _nødt_ til at angive hvordan det
skal initialiseres - eller kan man bruge tildeling.
Dette gælder f.eks. for klasser uden default constructor, eller for noget så
simpelt som en reference:

(ikke compileret - der kan være småfejl)
class foo
{
public:
foo(int& i_arg) :
i(i_arg) // brug af initializer liste er påkrævet!!!
{}

private:
int& i;
};

I C++ er der en væsentlig skelnen mellem initialisering (oprettelse af et
ikke tidligere eksisterende objekt - constructor) og tildeling (tildeling
til et allerede eksisterende objekt - assignment operator).

Almindeligvis foretrækker man brug af initializer listen frem for
assignment.
Dels fremgår det tydeligt (når man ved det - men sådan er det altid) at der
er tale om initialisering, dels kan der være en performance fordel.
F.eks.

(ikke compileret - der kan være småfejl)
class foo
{
public:
foo(const char* s_arg);

private:
std::string s;
};

hvis man skriver
foo::foo(const char* s_arg) :
s(s_arg)
{
}
bliver string objektet "s" initialiseret med den nul-terminerede tekst
"s_arg".

hvis man skriver
foo::foo(const char* s_arg)
{
s = s_arg;
}

bliver string objektet "s" default konstrueres (som en tom streng),
hvorefter det tildeles en værdi svarende til den nul-terminerede tekst
"s_arg".
Når man er inde i constructorens funktions-krop er alle dele af foo objektet
initialiseret.

Det svarer nogenlunde til forskellen mellem at skrive
std::string s1("Hello world!");
og
std::string s2;
s2 = "Hello world!";


Bemærk iøvrigt at rækkefølgen som man skriver initializer-listen ikke er
afgørende for hvilken rækkefølge den eksekveres.
Det er klasse-erklæringen der bestemmer det. Uden jeg skal gå ind i alle
detaljerne, så bliver basis-klassernes constructorer først kørt, hvorefter
data-medlemmer initialiseres i den rækkefølge de er erklæret.
Altså

class foo
{
public:
foo(int i_arg);
};

class bar : public foo
{
public:
bar(int i_arg, const char* s1_arg, const std::string& s2_arg);

private:
std::string s1;
std::string s2;
};

bar::bar(int i_arg, const char* s1_arg, const std::string& s2_arg) :
s2(s2_arg), // køres sidst
s1(s1_arg), // køres i midten
foo(i_arg) // køres først
{
}

Det er naturligvis anbefalelsesværdigt at skrive initialiserlisten således
at den eksekveres i samme rækkefølge som den skrive.

Venlig hilsen

Mogens Hansen



Mark Wrobel (25-12-2003)
Kommentar
Fra : Mark Wrobel


Dato : 25-12-03 22:34

Stort tak for svaret!!! Nu giver det hele mere mening.

Venlig hilsen
Mark


Søg
Reklame
Statistik
Spørgsmål : 177459
Tips : 31964
Nyheder : 719565
Indlæg : 6408182
Brugere : 218881

Månedens bedste
Årets bedste
Sidste års bedste