C++ Wird der Destruktor aufgerufen?

Barista

Top Contributor
Nach längerer Zeit beschäftige ich mich mal wieder mit C++, wobei ich sicher nie über die Anfänge hinaus gekommen bin.

Um mich fit zu machen, verwende ich Übungen aus diesem Buch:

Die C++-Challenge

Eine Aufgabe lautet, einen String als Titel auszugeben, indem jedes Wort groß geschrieben wird (der Wortanfang):

"the c++ challenger"

erwartet wird:

"The C++ Challenger"


Ich habe diese Aufgaben folgendermassen gelöst (VisualStudio):

[CODE lang="cpp" title="CapitalizeWords.cpp"]#include <iostream>

void capitalizeWords(
std::string& strToCapitalize)
{
if (strToCapitalize.size() < 1)
{
return;
}

strToCapitalize[0] = std::toupper(strToCapitalize[0]);

for (int i = 1; i < strToCapitalize.size() - 1; ++i)
{
if (strToCapitalize == ' ')
{
strToCapitalize[i + 1] = std::toupper(strToCapitalize[i + 1]);
}
}
}

int main()
{
std::string strToCapitalize("the c++ challenger");
std::cout << strToCapitalize << std::endl;
capitalizeWords(strToCapitalize);
std::cout << strToCapitalize << std::endl;
}
[/CODE]

Beim Entwickeln hatte ich einen Fehler, ich habe den String nicht als Referenz an die Funktion capitalizeWords übergeben.

[CODE lang="cpp" title="CapitalizeWords.cpp mit Fehler keine Übergabe per Referenz"]#include <iostream>

void capitalizeWords(
std::string strToCapitalize)
{
if (strToCapitalize.size() < 1)
{
return;
}

strToCapitalize[0] = std::toupper(strToCapitalize[0]);

for (int i = 1; i < strToCapitalize.size() - 1; ++i)
{
if (strToCapitalize == ' ')
{
strToCapitalize[i + 1] = std::toupper(strToCapitalize[i + 1]);
}
}
}

int main()
{
std::string strToCapitalize("the c++ challenger");
std::cout << strToCapitalize << std::endl;
capitalizeWords(strToCapitalize);
std::cout << strToCapitalize << std::endl;
}
[/CODE]

Erschreckend finde ich , dass beide Varianten problemlos kompilieren, offensichtlich kann in C++ die linke Seite einer Zuweisung bestimmen, was passiert.

Später fiel mir ein, dass in der falschen Variante ein Kopieren statt findet und am Ende der Funktion capitalizeWords der Destruktor aufgerufen werden müsste.

Leider weiss ich nicht, wie man sich anzeigen lassen kann, was C++ da eigentlich macht.

Ich habe irgendwo (wahrscheinlich iX) mal was gelesen über

C++ Insights

C++ Insights zeigt mir in der falschen Variante folgendes:

[CODE lang="cpp" title="StringCapitalize ohne Übergabe als Referenz als Ausgabe von C++ Insights"]#include <iostream>

void capitalizeWords(std::basic_string<char> strToCapitalize)
{
if(strToCapitalize.size() < 1) {
return;
}

strToCapitalize.operator[](0) = static_cast<char>(toupper(static_cast<int>(strToCapitalize.operator[](0))));
for(int i = 1; static_cast<unsigned long>(i) < (strToCapitalize.size() - 1); ++i) {
if(static_cast<int>(strToCapitalize.operator[](i)) == static_cast<int>(' ')) {
strToCapitalize.operator[](static_cast<unsigned long>(i + 1)) = static_cast<char>(toupper(static_cast<int>(strToCapitalize.operator[](static_cast<unsigned long>(i + 1)))));
}

}

}


int main()
{
std::string strToCapitalize = std::basic_string<char>("the c++ challenger", std::allocator<char>());
std::eek:perator<<(std::cout, strToCapitalize).operator<<(std::endl);
capitalizeWords(std::basic_string<char>(strToCapitalize));
std::eek:perator<<(std::cout, strToCapitalize).operator<<(std::endl);
}
[/CODE]

Der Destruktor des Parameter-Strings strToCapitalize wird nicht aufgerufen.

Hätte ich jetzt ein Speicherloch oder zeigt mir C++ Insights den Destruktor nicht an?

Vielen Dank
 

mihe7

Top Contributor
Bei der Variante ohne Referenz wird beim Aufruf der Funktion der Copy-Konstruktor und beim Verlassen der Destruktor aufgerufen.

Leg Dir einfach mal eine Klasse mit Konstruktor, Copy-Konstruktor und Destruktor mit entsprechenden Ausgaben sowie zwei Funktionen (einmal mit und einmal ohne Referenz) an. Dann siehst Du gleich, was passiert :)
 

Barista

Top Contributor
Leg Dir einfach mal eine Klasse mit Konstruktor, Copy-Konstruktor und Destruktor mit entsprechenden Ausgaben sowie zwei Funktionen (einmal mit und einmal ohne Referenz) an. Dann siehst Du gleich, was passiert
Ist diese Vorgehensweise verlässlich?

Wenn man mit Strg-Mausklick-links in den Code von std::string eintaucht (was wiederum zu std::basic_string führt) sieht einiges nach meinem Verdacht Microsoft-spezifisch aus.

Am liebsten wäre mir eine klare Anzeige in der IDE. Leider kenne ich mit Visual-Studio nicht aus.
 

mihe7

Top Contributor
C++:
#include <iostream>
#include <string>

class A {
private:
    int value;

public:
    A(int value) : value(value) {
        std::cout << "constructor A: " << this << std::endl;
    }

    A(const A& a) : value(a.value) {
        std::cout << "copy-ctr A: " << &a << "->" << this << std::endl;
    }

    virtual ~A() {
        std::cout << "destructor A: " << this << std::endl;
    }

    void show() {
        std::cout << this << std::endl;
        std::cout << value << std::endl;
    }
};

void showRef(A& a) {
    std::cout << "showRef()" << std::endl;
    a.show();
}

void showCopy(A a) {
    std::cout << "showCopy()" << std::endl;
}

int main(int argc, char *argv[]) {
    A a(5);
    a.show();
    showCopy(a);
    showRef(a);
    return 0;
}

liefert z. B.
Code:
constructor A: 0xbfb42e70
0xbfb42e70
5
copy-ctr A: 0xbfb42e70->0xbfb42e78
showCopy()
destructor A: 0xbfb42e78
showRef()
0xbfb42e70
5
destructor A: 0xbfb42e70
 

Neue Themen


Oben