Чудеса С++: разные формы вызова конструктора копирования 1

Posted by Андрей on Февраль 04, 2008

Что происходит, когда мы пишем A a(3), A a = 3 и A a = A(3)? Меня этот вопрос давно интересовал. Конечно, у класса должны быть корректные конструкторы, в том числе и копирования, операторы присваивания и т.п.

Проведем следственный эксперимент…

#include <stdio.h>

class A
{
    public:
    A() 
    {
        printf("A::A()\n");
    }

    A(int) 
    {
        printf("A::A(int)\n");
    }

    A(int, int) 
    {
        printf("A::A(int, int)\n");
    }

    A(const A& a) 
    {
        printf("A::A(const A& a)\n");
    }

    void operator=(const A& a) 
    {
        printf("A::operator=(const A& a)\n");
    }
};

int main()
{
    printf("=> A a1;\n");
    A a1;
    printf("=> A a2(3);\n");
    A a2(3);
    printf("=> A a3;\n");
    A a3 = 3;
    printf("=> A a4 = A(3);\n");
    A a4 = A(3);
    printf("=> A a5; a5 = A(3);\n");
    A a5; a5 = A(3);
    printf("=> A a6(a1);\n");
    A a6(a1);
    printf("=> A a7(4,4);\n");
    A a7(4, 4);
    printf("=> A a8 = A(4,4);\n");
    A a8 = A(4, 4);
    return 0;
}

Выведет на экран:

=> A a1;
A::A()
=> A a2(3);
A::A(int)
=> A a3;
A::A(int)
=> A a4 = A(3);
A::A(int)
=> A a5; a5 = A(3);
A::A()
A::A(int)
A::operator=(const A& a)
=> A a6(a1);
A::A(const A& a)
=> A a7(4,4);
A::A(int, int)
=> A a8 = A(4,4);
A::A(int, int)

Т.е. каждый раз вызывается обычный конструктор и все три формы, приведённые в начале поста, эквивалентны.

Однако стоит нам конструктор копирования объявить private, и сразу же получим вот это:

[smir@smira Teaching]$ g++ test.cxx 
test.cxx: In function ‘int main()’:
test.cxx:22: ошибка: ‘A::A(const A&)’ is private
test.cxx:39: ошибка: в данном контексте
test.cxx:22: ошибка: ‘A::A(const A&)’ is private
test.cxx:39: ошибка: в данном контексте
test.cxx:39: ошибка:   initializing temporary from result of ‘A::A(int)’
test.cxx:22: ошибка: ‘A::A(const A&)’ is private
test.cxx:41: ошибка: в данном контексте
test.cxx:22: ошибка: ‘A::A(const A&)’ is private
test.cxx:41: ошибка: в данном контексте

Строка 22 – это объявление конструктора копирования, а 39 и 41 это обращения A a3 = 3 и A a4 = A(3);. Интересно получается, что хотя конструктор копирования и не вызывается, но эти формы требуют его открытости. Это стандарт C++, оптимизация gcc или что-то ещё?

Trackbacks

Use this link to trackback from your own site.

Comments

Leave a response

  1. mail Вт, 15 Дек 2009 15:32:38 UTC

    Спасибо, случайно помогло в работе.

Comments