c ++ проблемы с временными объектами ostream

Я думал, чтобы преобразовать этот рабочий код:

ofstream outfile("my_file.txt");
copy(v.begin(), v.end(), ostream_iterator<int>(outfile));

в это:

copy(v.begin(), v.end(), ostream_iterator<int>(ofstream("my_file.txt")));

Другими словами, я использую «анонимную» или безымянную версию объекта ofstream.

Два вопроса:

(1) Почему вторая попытка не удалась?

(2) Является ли вторая попытка даже хорошей стилистически, или лучше в C ++ сохранять все явно именованными? Я пришел из фона Python, где объекты создаются на лету все время.

Спасибо!!

4

Решение

ostream_iterator<T> конструктор принимает неconst ссылка к объекту потока, в то время как временные значения могут быть переданы максимально const ссылки (по крайней мере, в C ++ 03); обоснование этого хорошо объясняется в этот вопрос.

Кстати, здесь не было большого выбора о том, как передать поток: const ссылка не имела бы смысла ( ostream_iterator имеет изменить поток), и простой ostream неприемлемо, потому что это не копируемое (нарезка убила бы полиморфизм).

В Python вы можете с легкостью создавать / передавать вещи на лету, потому что вы всегда имеете дело с Рекомендации в счетчиком ссылок (и сборщик мусора) объекты.

Семантика объекта C ++ радикально отличается — объект является объект, а не ссылка; чтобы получить семантику, аналогичную Python, вы должны динамически распределять каждый объект с помощью new и передать их, завернутые в shared_ptr<T>,

лучше ли в C ++ держать все явно названным

Не обязательно — это совершенно нормально для создания временных, но вы должны знать, что вы можете и не можете с ними делать, как ссылки влияют на их жизнь и т. Д.

3

Другие решения

Я получаю следующее сообщение об ошибке от моего компилятора, которое объясняет это.

std::ostream_iteratorконструктор принимает не константную ссылку. Не существует версии конструктора, которая принимает std :: ofstream.

Untitled 33.cpp:21: error: no matching function for call to ‘std::ostream_iterator<int, char, std::char_traits<char> >::ostream_iterator(std::ofstream)’
/usr/include/c++/4.2.1/bits/stream_iterator.h:185: note: candidates are: std::ostream_iterator<_Tp, _CharT, _Traits>::ostream_iterator(const std::ostream_iterator<_Tp, _CharT, _Traits>&) [with _Tp = int, _CharT = char, _Traits = std::char_traits<char>]
/usr/include/c++/4.2.1/bits/stream_iterator.h:181: note:                 std::ostream_iterator<_Tp, _CharT, _Traits>::ostream_iterator(std::basic_ostream<_CharT, _Traits>&, const _CharT*) [with _Tp = int, _CharT = char, _Traits = std::char_traits<char>]
/usr/include/c++/4.2.1/bits/stream_iterator.h:169: note:                 std::ostream_iterator<_Tp, _CharT, _Traits>::ostream_iterator(std::basic_ostream<_CharT, _Traits>&) [with _Tp = int, _CharT = char, _Traits = std::char_traits<char>]
0

В C ++ мы также часто создаем объекты «на лету», но вопросы владения должны решаться.

Проблема с ostream_iterator<int>(ofstream("my_file.txt")) является то, что временный объект передается в конструктор, но построенный ostream_iterator Объект не берет на себя ответственность за временные обязанности. Если ostream_iterator также не был временным, он продолжал содержать недопустимую ссылку на следующую строку кода.

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

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

Если вам это не нравится, вы можете чаще использовать общие указатели. Этот шаблон позволяет разделить владение между несколькими ссылками, при этом контейнер скрыт. Но это не часть iostreams, и как дизайнерское решение это было бы немного сомнительно здесь.

0
По вопросам рекламы [email protected]