/ 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
Constructor og destructor-kald i C++
Fra : Morten Bakkedal


Dato : 26-05-03 20:14

Hej

Jeg er lige startet på C++, og undrer mig over, at der i nedenstående
eksempel er uoverensstemmelse mellem antallet af constructor og
destructor-kald. Jeg er bekendt med, at man i stedet for at oprette en
lokal variabel, kan bruge konstruktionen "return Integer(x.a + y.a)", men
jeg har brug for at kunne lave mere komplicerede manipulationen med z,
før den retuneres.

Jeg har en teori om, at "return" blot laver en komplet kopi af z, og at de
to destructor-kald ("~Integer(3)") svarer til originalen og kopien,
men jeg vil gerne være sikker på, at jeg senere ender med at frigive den
samme hukommelse to gange. Derfor beder jeg om jeres vurdering af, om
nedenstående er helt efter bogen.

Compileren er GNU C++.

/* integer.cpp */

#include <iostream.h>

class Integer
{
int a;
public:
Integer(int aa);
~Integer();
friend Integer operator+(Integer& x, Integer& y);
};

Integer::Integer(int aa)
{
a = aa;
cout << "Integer()\n";
}

Integer:Integer()
{
cout << "~Integer(" << a << ")\n";
}

Integer operator+(Integer& x, Integer& y)
{
Integer z(x.a + y.a);
/* Her skal der laves manipulationer med z */
return z;
}

int main()
{
Integer x(1), y(2);

cout << "[\n";
Integer z = x + y;
cout << "]\n";

return 0;
}

/* Output:

Integer()
Integer()
[
Integer()
~Integer(3)
]
~Integer(3)
~Integer(2)
~Integer(1)

*/

--
Morten Bakkedal
http://www.bakkeland.dk/

 
 
Ivan Johansen (26-05-2003)
Kommentar
Fra : Ivan Johansen


Dato : 26-05-03 20:47


Morten Bakkedal wrote:
> Jeg har en teori om, at "return" blot laver en komplet kopi af z, og at de
> to destructor-kald ("~Integer(3)") svarer til originalen og kopien,

Det er korrekt. Hvis du laver en copy constructor kan du se det:
Integer::Integer(const Integer &Int)
{
a = Int.a;
cout << "Integer()\n";
}

> #include <iostream.h>

Der er ikke noget der hedder <iostream.h>, men der er noget der hedder
<iostream>.

> friend Integer operator+(Integer& x, Integer& y);
Da du hverken ændrer på x eller y bør de være const:
friend Integer operator+(const Integer& x, const Integer& y);


Ivan Johansen


Morten Bakkedal (26-05-2003)
Kommentar
Fra : Morten Bakkedal


Dato : 26-05-03 21:11

On Mon, 26 May 2003 21:46:32 +0200, Ivan Johansen wrote:

> Det er korrekt. Hvis du laver en copy constructor kan du se det:
> Integer::Integer(const Integer &Int)
> {
> a = Int.a;
> cout << "Integer()\n";
> }

Ja, nu passer antallet.

>> #include <iostream.h>
>
> Der er ikke noget der hedder <iostream.h>, men der er noget der hedder
> <iostream>.

OK, jeg troede det var valgfrit.

>> friend Integer operator+(Integer& x, Integer& y);
> Da du hverken ændrer på x eller y bør de være const:
> friend Integer operator+(const Integer& x, const Integer& y);

Ja, det er nok smart at gøre "brugere" af min klasse (og mig selv)
opmærksom på, at jeg faktisk ikke har tænkt mig at ændre på x og y.

--
Morten Bakkedal
http://www.bakkeland.dk/

Henrik Lynggaard (04-06-2003)
Kommentar
Fra : Henrik Lynggaard


Dato : 04-06-03 18:18

Morten Bakkedal wrote:
> On Mon, 26 May 2003 21:46:32 +0200, Ivan Johansen wrote:

>>>#include <iostream.h>
>>
>>Der er ikke noget der hedder <iostream.h>, men der er noget der hedder
>><iostream>.
>
>
> OK, jeg troede det var valgfrit.

Faktisk er det lidt mere komplekst.Det er nemlig to forskellige ting.

iostream.h er den gammeldags, C arvede/før C++ standarlisering filen

iostrem er den nye standard fil, som er i std:: namespacet

Hvis du søger på iostream der hvor din C++ compiler har sine system
include vil du finde dem begge, f.eks. min gcc 3.2

/usr/lib/gcc-lib/i686-pc-linux-gnu/3.2.3/include/g++-v3/iostream
/usr/lib/gcc-lib/i686-pc-linux-gnu/3.2.3/include/g++-v3/backward/iostream.h

mvh
henrik



Mogens Hansen (04-06-2003)
Kommentar
Fra : Mogens Hansen


Dato : 04-06-03 19:32


"Henrik Lynggaard" <henrik@lynggaard.org> wrote

[8<8<8<]
> iostream.h er den gammeldags, C arvede/før C++ standarlisering filen

Headerfilen iostream.h har aldrig været en del af C, og dermed er det ikke
noget der er arvet fra C.
Det er navnet på headerfilen som den oprindelige (før C++ Standarden, før
ca. 1997) iostream implementering var erklæret.

[8<8<8<]
> Hvis du søger på iostream der hvor din C++ compiler har sine system
> include vil du finde dem begge,

Hvad får dig til at tro det ?
Der er ikke noget krav om at en C++ compiler indeholder den, og man må
forvente at den efterhånden bliver fjernet.
F.eks.:

F:\Program Files\Microsoft Visual Studio .NET 2003>dir /s iostream.h
Volume in drive F is EXT_DRIVE
Volume Serial Number is E4CA-F53E
File Not Found


Venlig hilsen

Mogens hansen



Henrik Lynggaard (04-06-2003)
Kommentar
Fra : Henrik Lynggaard


Dato : 04-06-03 19:47

Mogens Hansen wrote:
> "Henrik Lynggaard" <henrik@lynggaard.org> wrote
>

> Hvad får dig til at tro det ?
> Der er ikke noget krav om at en C++ compiler indeholder den, og man må
> forvente at den efterhånden bliver fjernet.
> F.eks.:
>
> F:\Program Files\Microsoft Visual Studio .NET 2003>dir /s iostream.h
> Volume in drive F is EXT_DRIVE
> Volume Serial Number is E4CA-F53E
> File Not Found

Min nuværende gcc compiler har den under linux.

Jeg har lige været på kursus idag, og da arbejdede vi også med visual
studio 2003. Den havde begge filer, så måske afhænger det af hvilke
komponenter der er indstalleret.

Jeg kan ikke huske hvor den lå, men jeg kan kontrollere om den ligger på
min arbejds pc imorgen.

mvh
henrik





Mogens Hansen (04-06-2003)
Kommentar
Fra : Mogens Hansen


Dato : 04-06-03 20:36


"Henrik Lynggaard" <henrik@lynggaard.org> wrote

[8<8<8<]
> Min nuværende gcc compiler har den under linux.

Og hvad viser det - altså udover at din nuværende compiler under linux har
den ?

>
> Jeg har lige været på kursus idag, og da arbejdede vi også med visual
> studio 2003. Den havde begge filer, så måske afhænger det af hvilke
> komponenter der er indstalleret.

Jeg er ret sikker på at du tager fejl.
Microsoft Visual Studio .NET 2003 indeholder ikke både "iostream" og
"iostream.h".
I den foregående version (Visual Studio .NET), fik man så vidt jeg husker en
compiler warning, når man includerede "iostream.h", som sagde at den fil
ville forsvinde i næste version af compileren.
Det er rimeligt nok, her 5-6 år efter C++ Standarden blev afsluttet.

Iøvrigt er der en del forskel på klasserne der oprindelig fandtes i
"iostream.h" og klasserne der findes i "iostream".
F.eks.
De oprindelige klasser var ikke templates, og var således ikke i stand til
at håndtere wchar_t.
Arvehierakiet er blevet lavet lidt om.
Der er blevet tilføjet locale.


Måske blander du det sammen med "Compatibility features" i C++ (C++
Standarden, Annex D).
Funktioner som C++ har arvet fra C (f.eks. strcmp), kan findes i 2 header
filer.
Een på formen "xxx.h" og een på formen "cxxx" (hvor "xxx" f.eks. er
"string")

Man kan altså enten ved at skrive
#include <cstring>

eller ved at skrive
#include <string.h>

Den sidste svarer til den første, blot med en
using std::strcmp;
(og tilsvarende for de øvrige funktioner)

[8<8<8<]
> Jeg kan ikke huske hvor den lå, men jeg kan kontrollere om den ligger på
> min arbejds pc imorgen.

Ok.

Venlig hilsen

Mogens Hansen



Henrik Lynggaard (05-06-2003)
Kommentar
Fra : Henrik Lynggaard


Dato : 05-06-03 18:21

Mogens Hansen wrote:
> "Henrik Lynggaard" <henrik@lynggaard.org> wrote

>>Jeg har lige været på kursus idag, og da arbejdede vi også med visual
>>studio 2003. Den havde begge filer, så måske afhænger det af hvilke
>>komponenter der er indstalleret.
>
>
> Jeg er ret sikker på at du tager fejl.

På vores arbejds pc'er kører vi desværre kun vs 7 (.net 2002), og her
kunne jeg finde begge filer.

Så jeg kan desværre ikke *bevise* at ms ikke har fjernet filen mellem vs
7 (.net 2002) og vs 7.1 (.net 2003), men vores lærer viste os filerne på
sin arbejdspc (på kursus stedet) og den kører vs 7.1 (.net 2003)

Min oprindelige pointe var netop at hvis man tror at <iostream.h> og
<iostream> er det samme, så risikerer man at få fat i den forkerte udgave.

Netop fordi det er forskellige klasser kan man risikere ubehagelige
sideeffekter hvis man får fat i den forkerte, hvis der er (u)tilsigtede
forskelle i implementeringen.

Det var derfor jeg ville gøre opmærksom på at kommentaren "der er intet
som hedder iostream.h" ikke er helt korrekt.


> Måske blander du det sammen med "Compatibility features" i C++ (C++
> Standarden, Annex D).
> Funktioner som C++ har arvet fra C (f.eks. strcmp), kan findes i 2 header
> filer.
> Een på formen "xxx.h" og een på formen "cxxx" (hvor "xxx" f.eks. er
> "string")

Nope.
>>Jeg kan ikke huske hvor den lå, men jeg kan kontrollere om den ligger på
>> min arbejds pc imorgen.

Som skrevet har vi desværre stadig kun vs 7.0, så jeg kan ikke *bevise*
at de ikke har fjernet filen, men jeg er 100% at den ikke er det,

mvh
henrik



Mogens Hansen (05-06-2003)
Kommentar
Fra : Mogens Hansen


Dato : 05-06-03 19:34


"Henrik Lynggaard" <henrik@lynggaard.org> wrote
> Mogens Hansen wrote:
> > "Henrik Lynggaard" <henrik@lynggaard.org> wrote
>
> >>Jeg har lige været på kursus idag, og da arbejdede vi også med visual
> >>studio 2003. Den havde begge filer, så måske afhænger det af hvilke
> >>komponenter der er indstalleret.
> >
> >
> > Jeg er ret sikker på at du tager fejl.
>
> På vores arbejds pc'er kører vi desværre kun vs 7 (.net 2002),

Ok.

> og her
> kunne jeg finde begge filer.

Ja, den har begge filer.

>
> Så jeg kan desværre ikke *bevise* at ms ikke har fjernet filen mellem vs
> 7 (.net 2002) og vs 7.1 (.net 2003), men vores lærer viste os filerne på
> sin arbejdspc (på kursus stedet) og den kører vs 7.1 (.net 2003)

Ja - hvad viser det ?
Jeg kan naturligvis ikke gøre rede for hvad jeres lærer har vist, eller hvad
du mener at have set.

Jeg har mange "iostream.h" liggende på min maskine, hvor Visual Studio .NET
2003 er installeret - de stammer blot ikke fra installation af Visual Studio
..NET 2003.

>
> Min oprindelige pointe var netop at hvis man tror at <iostream.h> og
> <iostream> er det samme, så risikerer man at få fat i den forkerte udgave.
>
> Netop fordi det er forskellige klasser kan man risikere ubehagelige
> sideeffekter hvis man får fat i den forkerte, hvis der er (u)tilsigtede
> forskelle i implementeringen.
>
> Det var derfor jeg ville gøre opmærksom på at kommentaren "der er intet
> som hedder iostream.h" ikke er helt korrekt.

Naturligvis er der noget der hedder "iostream.h".
Der er også noget der hedder "windows.h" og så meget andet.
Det har blot ikke noget med C++ Standarden at gøre.

Ydermere mener folk typisk "iostream" når de skriver "iostream.h" - de har
bare brugt gamle bøger eller på anden måde mangler opdateret viden (det har
været sådan i 5-6 år).
Så selv om Ivan Johansen's formulering måske ikke var fuldstændigt korrekt
og præcis, er der vist ikke noget at udsætte på budskabet. Det er svært at
være fuldstændig korrekt og præcis.

>
>
> > Måske blander du det sammen med "Compatibility features" i C++ (C++
> > Standarden, Annex D).
> > Funktioner som C++ har arvet fra C (f.eks. strcmp), kan findes i 2
header
> > filer.
> > Een på formen "xxx.h" og een på formen "cxxx" (hvor "xxx" f.eks. er
> > "string")
>
> Nope.

Nope til hvad ?
At at C headerne findes på formen "xxx.h" og "cxxx".
At du ikke blander forholdet mellem "iostream" og "iostream.h" sammen med C
compatibilitets features.


> >>Jeg kan ikke huske hvor den lå, men jeg kan kontrollere om den ligger på
> >> min arbejds pc imorgen.
>
> Som skrevet har vi desværre stadig kun vs 7.0, så jeg kan ikke *bevise*
> at de ikke har fjernet filen, men jeg er 100% at den ikke er det,

Jeg tror naturligvis på at du er 100 % sikker på at "iostream.h" er en del
af Visual Studio .NET 2003 - men du tager fejl.
Jeg _har_ checket på 3 forskellige maskiner.
Jeg checkede det naturligvis _inden_ jeg sagde at "iostream.h" ikke er en
del af Visual Studio .NET 2003.

Hvis man prøver at oversætte med Visual Studio .NET 2003:

#include <iostream.h>

int main()
{
cout << "Hello world!";
}

får man følgende fejlmelding:

g:\Documents and Settings\Administrator\My Documents\Visual Studio
Projects\fnyt\fnyt.cpp fatal error C1083: Cannot open include file:
'iostream.h': No such file or directory

Hvis du søger på Google vil du se at andre har haft samme oplevelse.

Jeg har også checket Visual Studio .NET (2002), og kan som dig konstatere at
"iostream.h" findes som en del af den installation.

Venlig hilsen

Mogens Hansen




Mogens Hansen (05-06-2003)
Kommentar
Fra : Mogens Hansen


Dato : 05-06-03 19:57


"Mogens Hansen" <mogens_h@dk-online.dk> wrote

[8<8<8<]
> #include <iostream.h>
>
> int main()
> {
> cout << "Hello world!";
> }

Prøv i øvrigt at oversætte samme program med Visual Studio .NET (2002).
Du vil se at man får en warning:
c:\Program Files\Microsoft Visual Studio .NET\Vc7\include\useoldio.h(29) :
warning C4995: '_OLD_IOSTREAMS_ARE_DEPRECATED': name was marked as #pragma
deprecated

og når man kigger nærmere på filen "useoldio.h", linie 20 kan man læse:

/*
* Warning C4995, '_OLD_IOSTREAMS_ARE_DEPRECATED' is a deprecated name, is
* being issued because the old I/O Streams headers iostreams.h et al will
no
* longer be supported from VC8. Replace references such as #include
* <iostreams.h> with #include <iostreams>, using the new, more conformant,
I/O
* Streams headers.
*/


Venlig hilsen

Mogens Hansen



Mogens Hansen (05-06-2003)
Kommentar
Fra : Mogens Hansen


Dato : 05-06-03 21:47


"Henrik Lynggaard" <henrik@lynggaard.org> wrote

[8<8<8<]
> Som skrevet har vi desværre stadig kun vs 7.0, så jeg kan ikke *bevise*
> at de ikke har fjernet filen, men jeg er 100% at den ikke er det,

Fra hjælpesystemet til Visual Studio .NET 2003, afsnittet "Visual C++
Concepts: Porting and Upgrading - Differences in iostream Implementation."

<citat>
The old iostream library was removed beginning in Visual C++ .NET 2003.

The main difference between the Standard C++ Library and previous run-time
libraries is in the iostream library. Details of the iostream implementation
have changed, and it may be necessary to rewrite parts of your code that use
iostream if you want to link with the Standard C++ Library.

You will have to remove any old iostream headers (fstream.h, iomanip.h,
ios.h, iostream.h, istream.h, ostream.h, streamb.h, and strstrea.h) you have
included in your code and add one or more of the new Standard C++ iostream
headers (<fstream>, <iomanip>, <ios>, <iosfwd>, <iostream>, <istream>,
<ostream>, <sstream>, <streambuf>, and <strstream>, all without the .h
extension).


</citat>

Venlig hilsen

Mogens Hansen



Per Abrahamsen (05-06-2003)
Kommentar
Fra : Per Abrahamsen


Dato : 05-06-03 13:09

"Mogens Hansen" <mogens_h@dk-online.dk> writes:

> "Henrik Lynggaard" <henrik@lynggaard.org> wrote
>
>> Hvis du søger på iostream der hvor din C++ compiler har sine system
>> include vil du finde dem begge,
>
> Hvad får dig til at tro det ?

Morten bruger en Unix newsreader med rødder i GNU/Linux miljøet, så
det er overvejende sandsynligt at hans systemcompiler er GCC.

Mogens Hansen (26-05-2003)
Kommentar
Fra : Mogens Hansen


Dato : 26-05-03 20:52


"Morten Bakkedal" <news20030429@bakkeland.dk> wrote

[8<8<8<]
> Jeg har en teori om, at "return" blot laver en komplet kopi af z, og at de
> to destructor-kald ("~Integer(3)") svarer til originalen og kopien,

Det er rigtigt.
Der er en speciel constructor, der hedder copy-constructor. Den bruges når
man laver en kopi af et objekt.
Hvis du ikke laver den, og du har brug for den, så laver compileren den for
dig.
Der findes en anden særlig funktion - copy-assignment - som man ofte har
brug for, hvis man har brug for selv at skrive copy-constructoren. Den
bruges når man tildeler et eksisterende objekt værdien fra et andet
eksisterende objekt.

Har du en bog, hvor du kan læse om copy-constructoren og copy-assignment ?

Bemærk i øvrigt at i det eksempel har compileren lov til at optimere det
ekstra objekt væk, så den sparer kaldet til copy-constructor og tilsvarende
destructor.
Udskriften fra dit program vil derfor kunne variere fra compiler til
compiler, og eventuelt også med compiler switche.


> men jeg vil gerne være sikker på, at jeg senere ender med at frigive den
> samme hukommelse to gange.

Jeg antager at du mener at du vil sikre dig at alle oprettede objekter
bliver nedlagt.
Så længe du ikke skriver "new" skal du ikke selv gøre noget for at nedlægge
objektet igen.


> Derfor beder jeg om jeres vurdering af, om
> nedenstående er helt efter bogen.

Ok.
Der er ikke alverden galt med det - du ser blot ikke alt hvad der sker.
Det får lige et par småting med

[8<8<8<]
> #include <iostream.h>

Det hedder
#include <iostream>
ifølge C++ Standarden.
Den anden måde er den gamle form fra før 1996-98.

> friend Integer operator+(Integer& x, Integer& y);

Lav parametrene være "const", for derved at lade compileren sikre at "x" og
"y" ikke ændres.

> };
>
> Integer::Integer(int aa)
> {
> a = aa;

Foretræk initialisering frem for assignment.

Integer::Integer(const Integer& src) :
a(src.a)
{


Altså
<modificeret kode>
#include <iostream>

using std::cout;

class Integer
{
int a;
public:
Integer(int aa);
Integer(const Integer& src);
~Integer();
friend Integer operator+(const Integer& x, const Integer& y);
};

Integer::Integer(int aa) :
a(aa)
{
cout << "Integer()\n";
}

Integer::Integer(const Integer& src) :
a(src.a)
{
cout << "Integer(const Integer&)\n";
}

Integer:Integer()
{
cout << "~Integer(" << a << ")\n";
}

Integer operator+(const Integer& x, const Integer& y)
{
Integer z(x.a + y.a);
return z;
}

int main()
{

Integer x(1), y(2);

cout << "[\n";
Integer z = x + y;
cout << "]\n";
}
</modificeret kode>

som skriver
<output 1>
Integer()
Integer()
[
Integer()
]
~Integer(3)
~Integer(2)
~Integer(1)
</output 1>

eller

<output 2>
Integer()
Integer()
[
Integer()
Integer(const Integer&)
~Integer(3)
]
~Integer(3)
~Integer(2)
~Integer(1)
</output 2>

afhængig af compiler

Venlig hilsen

Mogens Hansen



Henrik Lynggaard (04-06-2003)
Kommentar
Fra : Henrik Lynggaard


Dato : 04-06-03 18:20

Mogens Hansen wrote:
> "Morten Bakkedal" <news20030429@bakkeland.dk> wrote
>
>> friend Integer operator+(Integer& x, Integer& y);
>
>
> Lav parametrene være "const", for derved at lade compileren sikre at "x" og
> "y" ikke ændres.

Det er nok værd at bemærke at klassen som bruges som parameter skal være
"const korrekt" før det vil virke..

mvh
henrik


Mogens Hansen (04-06-2003)
Kommentar
Fra : Mogens Hansen


Dato : 04-06-03 19:33


"Henrik Lynggaard" <henrik@lynggaard.org> wrote

> Mogens Hansen wrote:
> > "Morten Bakkedal" <news20030429@bakkeland.dk> wrote
> >
> >> friend Integer operator+(Integer& x, Integer& y);
> >
> >
> > Lav parametrene være "const", for derved at lade compileren sikre at "x"
og
> > "y" ikke ændres.
>
> Det er nok værd at bemærke at klassen som bruges som parameter skal være
> "const korrekt" før det vil virke..


Selvfølgelig.
Det at skrive const er at gøre programmet mere const korrekt.

Var der noget i klassen "Integer" sammen med "operator+" i eksemplet, der
ikke er const korrekt ?

Venlig hilsen

Mogens Hansen



Henrik Lynggaard (04-06-2003)
Kommentar
Fra : Henrik Lynggaard


Dato : 04-06-03 20:28

Mogens Hansen wrote:
> "Henrik Lynggaard" <henrik@lynggaard.org> wrote
>

> Var der noget i klassen "Integer" sammen med "operator+" i eksemplet, der
> ikke er const korrekt ?
>
næ ikke umiddelbart. Jeg ville bare lige bemærke at det krævede
paremateren skulle være en const korrekt klasse. Hvis han havde kodet en
metode ala


void print(const Person& person)
{
   cout<< "Navnet" << person.getName() <<endl;
}

vil det ikke virke medmidre Person klassen er const korrekt.

bare en side-bemærkning.

mvh
Henrik




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

Månedens bedste
Årets bedste
Sidste års bedste