2013-08-24 5 views
1

Я нашел этот код где-то. Он печатает «abcd» на экране, но странным образом. Я хотел бы кто-то сказать мне, как это работает:Как работает этот код печати?

#include <iostream> 
#include <sstream> 

class X 
{ 
    typedef std::istreambuf_iterator<char> Iter; 
    Iter it; 
public: 
    X(std::streambuf* p) : it(p) { } 

    Iter begin() 
     { return it; } 
    Iter end() 
     { return Iter(); } 
}; 

void printbuf(X x, std::ostreambuf_iterator<char> it) 
{ 
    for (auto c : x) 
    { 
     *it = c; 
    } 
} 

int main() 
{ 
    std::stringbuf buf("abcd", std::ios_base::in | std::ios_base::out); 
    printbuf(&buf, std::cout); 
} 
+0

Можете ссылаться на то, где вы его нашли? – Borgleader

+0

@Borgleader Извините, он не был привязан к –

+0

. Вероятно, что это, скорее всего, вызывает смущение, это неявное построение * обоих параметров, переданных 'printbuf()'. Строка 'X' неявно построена по адресу' stringbuf', а 'std :: ostreambuf_iterator <>' также неявно построена из 'std :: cout'. Пройдите мимо этого, и это станет намного проще понять. – WhozCraig

ответ

4

У нас есть класс X который инкапсулирует istreambuf_iterator <char>. Это тип итератора, который позволяет обрабатывать буфер потока как диапазон итератора для стандартных алгоритмов.

class X 
{ 
    typedef std::istreambuf_iterator<char> Iter; 
    Iter it; 
public: 

Класс строится из указателя на экземпляр буфера потока.

X(std::streambuf* p) : it(p) { } 

Он предоставляет begin() и end() функции-члены, чтобы использовать его с расстояния на основе for цикла.

Iter begin() 
     { return it; } 
    Iter end() 
     { return Iter(); } 
}; 

printbuf() это функция, которая принимает экземпляр нашего диапазона класса X, а также в качестве ostreambuf_iterator <char>, который, как вы уже догадались, позволяет использовать буфер выходного потока в качестве выходного итератора.

void printbuf(X x, std::ostreambuf_iterator<char> it) 
{ 

Таким образом, мы перебираем каждый символ во входном диапазоне.

for (auto c : x) 
    { 

Если вы не имели дела с выходными итераторы раньше, вы можете думать о них как объект, похожий на указатель, к которому вы писать значения с помощью разыменования и назначение. back_insert_iterator является широко используемым выходным итератором для построения контейнеров - вы обычно строите его с помощью back_inserter. Но я отвлекся.

Копируем каждый символ на выходной итератор.

 *it = c; 
    } 
} 

int main() 
{ 

Здесь мы строим строковый буфер, который является как буфером ввода, так и выходным потоком. В этом примере мы используем только возможности ввода.

std::stringbuf buf("abcd", std::ios_base::in | std::ios_base::out); 

Теперь мы используем неявно построенную X экземпляр для лечения буфер строки в диапазоне итератора. Затем мы копируем этот диапазон в итератор буфера выходного потока, также неявно построенный - до std::cout.

printbuf(&buf, std::cout); 
} 

Эффект заключается в том, что мы перебираем каждый символ в буфере и копируем его на стандартный вывод.

2
printbuf(&buf, std::cout); 

Передача std::stringbuf* в качестве первого параметра Я вызывает неявное строительство X, чтобы соответствовать printbuf()

, а также для второго параметра, неявное происходит в строительстве, экземпляр std::ostreambuf_iterator<char> создается из std::cout (станд :: ostream)

void printbuf(X x, std::ostreambuf_iterator<char> it) 
{ 
    for (auto c : x) 
    { 
     *it = c; 
    } 
} 

В printbuf, цикл Еогеасп (диапазон основан на цикле) использует X::begin() и X::end() для перебрать все символы, которые обернуты std::stringbuf и записывает их в std::cout через std::ostreambuf_iterator (it)

Смежные вопросы