Here вы найдете следующие инструкции в разделе Какой заголовок?:Как схема ниже гарантирует, что будет только одно определение объектов cin, cout, ...?
Наконец,
<iostream>
обеспечивает восемь стандартных глобальных объектов (CIN, COUT и т.д.). Чтобы сделать это правильно, этот заголовок также содержит содержимое<istream>
и<ostream>
, но ничего больше. В содержания этого заголовка выглядеть
#include <ostream>
#include <istream>
namespace std
{
extern istream cin;
extern ostream cout;
....
// this is explained below
static ios_base::Init __foo; // not its real name
}
Теперь, во время выполнения пенальти упоминалось ранее: глобальные объекты должны быть инициализированы перед любыми из вашего собственного кода используют их; это , гарантированный стандартом. Как и любой другой глобальный объект, они должны быть инициализированы один раз и только один раз. Обычно это делается с конструкцией , подобной приведенной выше, и вложенным классом ios_base :: Init является , указанным в стандарте именно по этой причине.
Как это работает? Поскольку заголовок включен до любого из вашего кода , объект __foo создается до любого из ваших объектов. (Глобальные объекты построены в том порядке, в котором они объявлены, и уничтожены в обратном порядке.) При первом запуске конструктора устанавливаются восемь объектов потока .
Мой вопрос: когда я заголовочный файл <iostream>
в нескольких .cpp
файлов, как это схема выше гарантий, что будет только один определение объектов cin
, cout
и т.д ...?
«Одно определение» неинтересно - это только часть (скомпилированной) стандартной библиотеки. Что интересно, это «одна инициализация». (Я думаю, что эта техника называется [«Schwartz counter»] (http://stackoverflow.com/q/9251763/596781).) –
AFAIK, 'cout',' cin' и др. объекты просто объявляются как 'extern' в заголовке, фактические определения находятся внутри стандартных файлов lib. Теперь 'ios_base :: Init' объявляется' static', поэтому каждая единица перевода имеет свою собственную копию. Конструкторы/деструкторы объекта «Init» выполняют некоторый подсчет ссылок, чтобы знать, когда инициализировать/уничтожать стандартные потоковые объекты. По крайней мере, как это делает [stdlibC++] (http://gcc.gnu.org/viewcvs/trunk/libstdc%2B%2B-v3/include/std/iostream?view=markup). – jrok
@jrok Все, что вы сказали, мне ясно. Я не понимаю, как «ios_base :: Init» избегает нескольких определений глобальных объектов cin, cout, ..., когда '' включен в несколько файлов '.cpp'. –