Тема: Стандартні потоки С++.
Шановне панство! Питання життя і смерті. Я й раніше плавав у потоках, а зараз треба якнайдетальніше розібратися із ними. Є "кілька питань", я запишу їх у формі своїх доводів, а вас прошу підтвердити або спростувати їх. Ретельно прогуглити не маю часу(та й, чесно кажучи, бажання також), тож рятуйте.
1. Поток - об'єкт ios-послідовника. Чи можна створити об'єкт типу ios, і наскільки можливості будуть обмеженими?
2. Розумна книжка сказала: об'єкти cerr і clog не можуть бути перенаправленими. Що це означає? Що означає "перенаправити" потік? Можливо, в якесь відмінне від командного рядку місце? І взагалі, що означає, направити його, куди направлені cout та cin?
3. ios має вказівник на streambuf. Це клас, що відкриває/закриває потік на найелементарнішому рівні. Він є, таким собі, посередником між ios та ОЗУ.
4. Що означає "cerr не проходить буферизацію"? Тут я тоді не зрозумів: якщо ios (чи що там інше) може вивести і без буферизації, то навіщо вона тоді потрібна? Може у streambuf'і і виявляються хренові біти?
5. Чому зберігається саме вказівник на streambuf, а не цілий об'єкт? Можливо, через ефективність, якої можна досягти в умовах частого послідовного відкривання/закривання потоків і відповідно динамічного створення/видалення об'єкту. Але це слово "послідовно" мене насторожує. Адже потоків може бути відкрито одночасно кілька(теоретично, це можливо). Як тоді працює streambuf? Не може ж бути у кожного файлу власний streambuf. Тоді б була така плутанина, якщо кожному треба то відкрити, то закрити потік, хоча... якщо це вказівник, і пам'ять виділяється нестатично, тобто не з стеку, а з купи, там такої проблеми не повинно б бути.
Або може Страуструп передбачав часту зміну інтерфейсу/реалізації streambuf'а і хотів уберегти користувачів бібліотеки std від перекомпіляції цілого проекту.
6. Шо се таке:
(cin>>size[i]).get();
7. Я працював над створенням функцій, що безпечно отримують з потоку true-дані у відповідності до певного типу. Це було так: отримав стрінгу, розпарсив її і вирішив, що робити вже далі: бед-біт ставити чи що далі робити. Як це реалізовано в "operator>>" із стандартними типами? Адже там однак отримується відпочатку рядок символів, а у streambuf'і вже він, мабуть, розбирається? Якщо не зрозуміло, то так: що робить cin>>intVar; якщо, як не крути, маємо спочатку рядок символів?
8. Всілякі failbit, badbit можна встановлювати у будь-якому потоці, бо всі класи наслідують ios, у якому і визначаються всі флаги.
9. Як встановлюються failbit, badbit самою cin.get(...)? Як вона може зрозуміти, що вхідні дані несумісні із типом, який ці дані отримує? Чи тут також працює якась таємнича сила оператору ">>"(і це, скоріше за все, є підтвердженням того, про що я казав у п.7: спочатку маємо рядок символів)?
10. Коли встановлюється якийсь флаг статусу помилки, програма, ніби, завмирає. Що насправді відбувається? Я ж можу спитати у потока, чи все добре і те галудження буде працювати.
cin>>var; //тут користувач шось не те тикає
if( !cin.good() ) { //і що ми маємо:
//цей код виконується,
//і якось починаємо виправляти помилку.
}
Я думаю, що просто завмирає сам потік. Програма починає виконуватися далі, а при намаганні скористатися потоком із бед-бітом вся інформація ігнорується.
11. Я не пробував, але мені здається, що при failbit у якомусь потоці протилежно направлений потік може нормально працювати(н-д, у вхідному якийсь ерор, а вихідний може писати). Чи я правий?
12. Що означає відкрити файл? Пишуть, що "отримати доступ", але на діях - це що? Я думав, що це "завантажити до оперативки".
13. Коли я, прочитавши з файлу щось, перемістився на, припустимо, 20 символів, то тепер вказівник об'єкту вказує на ту позицію, на якій я закінчив зчитування.
14. Я ж можу отримати з файлу кілька рядків одночасно в одну змінну таким чином?
char* str[MAX]; //рядок для вхідних даних
somefile.getline(str, MAX, ifstream() ); //param1 - рядок, у який зчитуємо;
//param2 - довжина; param3 - символ, на якому
//закінчуємо зчитування. Пустий конструктор
//ifstream() повертає символ кінця потоку
Дякую за те, що дочитали до цього рядка, уявляю той піздецьжах, який охопив вас, мабуть вже на 7 пункті, але іншого виходу не маю, вибачайте.
Ще одне питання не по темі:
В чому перевага static_cast<T>(U), reinterpret_cast<T*>(U*) перед тими, що С++ дістав від С?
(Про унікальність і небезпечність const_cast<T&>(const T) я знаю.)