C++, почему конструктор в этом примере вызван дважды?

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

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

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

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

5
задан genesys 8 January 2010 в 12:47
поделиться

3 ответа

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

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

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);

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

7
ответ дан 18 December 2019 в 10:44
поделиться

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

Это A (3.5F) .

Затем создайте A , скрывая A к A . Таким образом, конструктор впервые вызывается для A . Вызывается Copy-Constructor из A .

3
ответ дан 18 December 2019 в 10:44
поделиться

Похоже, что только NTFS поддерживает пробивание отверстий. Исторически это было проблемой в большинстве файловых систем. POSIX, насколько мне известно, не определяет интерфейс ОС для пробивания дыр, поэтому ни одна из стандартных файловых систем Linux не имеет его поддержки. NetApp поддерживает пробивание отверстий через Windows в файловой системе WAFL . Есть хорошее сообщение в блоге об этом здесь .

Для вашей проблемы, как указали другие, единственным решением является перемещение файлов, не содержащих блоков, содержащих нули. Да, это будет медленно. Или напишите расширение для вашей файловой системы в Linux, которое сделает это, и отправьте исправление хорошим сотрудникам в группе ядра Linux.;)

Изменить: Похоже, XFS поддерживает пробивание отверстий. Проверьте этот поток .

Другим действительно искаженным вариантом может быть использование отладчика файловой системы для перехода и пробивания дыр во всех косвенных блоках, которые указывают на обнуление блоков в файле (возможно, вы можете создать сценарий). Затем запустите fsck, который исправит все связанные счетчики блоков, соберет все потерянные блоки (обнуленные блоки) и поместит их в потерянный + найденный каталог (их можно удалить, чтобы освободить место) и исправит другие свойства в файловой системе. Страшно, да?


Отказ от ответственности: делайте это на свой страх и риск. Я не несу ответственности за потерю данных. ;)

-121--2827397-

Я использовал информацию на этом посту для небольшого образца, который я строил. Это код, который я использовал при запуске воспроизведения, чтобы предотвратить остановку звука:

AudioSession.Category = AudioSessionCategory.MediaPlayback;

Когда приложение завершит воспроизведение, чтобы восстановить исходное значение:

AudioSession.Category = AudioSessionCategory.SoloAmbientSound;

Полный образец:

http://github.com/migueldeicaza/monotouch-samples/tree/master/StreamingAudio/

-121--1513805-

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

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

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

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

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

6
ответ дан 18 December 2019 в 10:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: