Chciałbym zrealizować inicjalizację obiektów tablicowych za pomocą instrukcji inicjowania w następujący sposób.

TestClass array[5] = {
    TestClass("test1"),
    TestClass("test2"),
    TestClass("test3"),
    TestClass("test4"),
    TestClass("test5")
};

Według pewnej autorytatywnej książki, takiej jak ARM (podręcznik z adnotacjami) dla C++, wydaje się, że mówi, że jest to sposób na zainicjowanie tablicy obiektów, która ma konstruktor / destruktor. Po tym właśnie stworzyłem następujący przykładowy kod i zobaczę, co się stanie.

#include <iostream>
#include <sstream>
#include <string>

class TestClass
{
public:

    TestClass(const char* name) : name_(name)
    {
        std::cout << "Ctor(const char*) : " << name_ << std::endl;
    }

    ~TestClass()
    {
        std::cout << "Dtor() : " << name_ << std::endl;
    }

    TestClass() : name_("")
    {
    }

    void print()
    {
        std::cout << "obj:" << name_ << std::endl;
    }
private:
    TestClass(const TestClass& rhs);

    std::string name_;
};

int main()
{
    TestClass   array[5] = {
        TestClass("test1"),
        TestClass("test2"),
        TestClass("test3"),
        TestClass("test4"),
        TestClass("test5")
    };

    for (unsigned int i = 0; i < sizeof(array)/sizeof(array[0]); ++i) {
        array[i].print();
    }

    return EXIT_SUCCESS;
}

Jeśli chodzi o pierwszą próbę kompilacji powyższego kodu źródłowego przy użyciu GNU GCC (4.1.2), nie udało się wygenerować czegoś takiego jak poniżej.

error: ‘TestClass::TestClass(const TestClass&)’ is private

Zrozumiałem więc, że oznacza to, że aby umożliwić inicjalizację tablicy obiektów, wymagałoby to „konstruktora kopiowania”. Następnie spróbowałem skompilować powyższy kod, wprowadzając zdefiniowany przez użytkownika (publiczny) konstruktor kopiujący w następujący sposób.

TestClass::TestClass(const TestClass& rhs) : name_(rhs.name_)
{
    std::cout << "Copy Ctor : " << name_ << std::endl;
}

Udało mi się skompilować kod źródłowy. Jednak po wykonaniu programu, który został zbudowany powyżej, otrzymałem następujące dane wyjściowe.

Ctor(const char*) : test1
Ctor(const char*) : test2
Ctor(const char*) : test3
Ctor(const char*) : test4
Ctor(const char*) : test5
obj:test1
obj:test2
obj:test3
obj:test4
obj:test5
Dtor() : test5
Dtor() : test4
Dtor() : test3
Dtor() : test2
Dtor() : test1

Chciałbym wiedzieć, co następuje,

  1. Dlaczego nie możemy uczynić konstruktora kopiującego zadeklarowanym jako prywatny?

  2. Dlaczego nie jest wywoływany konstruktor kopiujący zdefiniowany przez użytkownika (spodziewałem się, że dane wyjściowe powinny zawierać gdzieś „Copy Ctor: xxxx”. Ale nie mogłem tego uzyskać. Zrozumiałem więc, że konstruktor kopiujący zdefiniowany przez użytkownika nie został wywołany).

Właściwie nie jestem pewien, czy powyższe jest specyficzne dla GNU GCC, czy jest to specyfikacja języka C++... Byłoby mile widziane, gdyby ktoś z was podał mi poprawny wskaźnik do powyższego.

8
Smg 30 maj 2011, 17:21
2
Możesz przetestować z -fno-elide-constructors .
 – 
CB Bailey
30 maj 2011, 17:24
 – 
Nawaz
30 maj 2011, 17:28

2 odpowiedzi

Najlepsza odpowiedź

Niezależnie od tego, czy konstruktor kopiujący jest używany przez kompilator, musi być dostępny - tj. nie może być prywatny. W takim przypadku kompilator może uniknąć używania konstruktora kopiującego, używając bezpośrednio konstruktora const char *, ale nadal potrzebuje dostępnego konstruktora kopiującego. Jest to coś, czego nie obejmuje ARM, który jest przestarzały.

3
user2100815user2100815 30 maj 2011, 17:25
Dziękuję za jasną odpowiedź. Teraz mogę wyraźnie odnieść się do.
 – 
Smg
30 maj 2011, 18:07

Kompilator pomija kopię, ale konstruktor kopiujący nadal musi być dostępny.

4
Björn Pollex 30 maj 2011, 17:23