c ++, почему конструктор в этом примере вызывается дважды? - PullRequest
5 голосов
/ 08 января 2010

Я просто пытаюсь понять поведение следующей ситуации:

template <typename T1>
struct A{
    template <typename T2>
    A(T2 val){
        cout<<"sizeof(T1): "<<sizeof(T1)<<" sizeof(T2): "<<sizeof(T2)<<endl;
    }
    T1 dummyField;
};

так - класс шаблонируется с T1, а конструктор - с T2

сейчас - если я напишу:

A<bool> a = A<bool>(true);

вывод соответствует ожидаемому:

sizeof(T1): 1 sizeof(T2): 1

однако - если я напишу:

A<bool> a = A<float>(3.5f);

вывод:

sizeof(T1): 4 sizeof(T2): 4
sizeof(T1): 1 sizeof(T2): 4

почему конструктор вызывается дважды с параметром шаблона float?

спасибо за удовлетворение моего любопытства

Ответы [ 3 ]

7 голосов
/ 08 января 2010

Как избежать копирования?

В обоих случаях вызываются два конструктора, однако вы не видите его в первом случае, поскольку один из них является сгенерированным компилятором. Если вы хотите избежать копирования, вам нужно использовать другой синтаксис, такой как:

A<bool> a(true);

A<bool> a(3.5f);

Почему (и какой) конструктор копирования называется?

A<bool> a = A<bool>(true);

Здесь конструктор A (bool val) используется для создания временного значения, в то время как конструктор копирования, сгенерированный компилятором по умолчанию, используется для копирования A в A. Вы копируете тот же тип, а для конструктора копирования того же типа используемый. Интересный и неочевидный факт: Конструктор шаблона никогда не используется в качестве конструктора копирования, даже если он выглядит как один.

A<bool> a = A<float>(3.5f);

Здесь конструктор A<float>(float val) используется сначала для создания временного значения, а затем для выполнения копирования используется шаблонный конструктор A<bool>( A<float> val).

6 голосов
/ 08 января 2010

в вашем первом примере вы делаете неявный вызов конструктора копирования

A<bool>(A<bool> const&)

во втором примере это не будет работать, так как у вас есть два разных типа поэтому компилятор должен использовать ваш шаблонный конструктор для создания нового объекта объявляя

 template <typename T2>
A(A<T2>const& val){
    cout<<sizeof(val.dummmyField)<<endl;
}

должно прояснить это

3 голосов
/ 08 января 2010

Потому что вы сначала создаете float-экземпляр класса шаблона.

Это A<float>(3.5f) -Часть.

Затем создайте A<bool>, преобразовав A<float> в A<bool>. Таким образом, конструктор сначала вызывается для A<float> -экземпляра. Копируется конструктор A<bool>.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...