Повторение решения первого сообщения более абстрактным образом:
>>> x = [1, 2, 3, 4, 2, 2, 3]
>>> while 2 in x: x.remove(2)
>>> x
[1, 3, 4, 3]
Извините, ваш профессор ошибся. Вы должны использовать взаимное исключение или некоторые другие барьеры, чтобы гарантировать непрерывное использование общего ресурса (который в данном случае является выходным файлом STDOUT
).
Смешанный вывод - потенциально ожидаемое поведение, независимо от printf
или std::cout::operator<<()
. Различия в поведении, которые вы видите, - это тонкие различия в продолжительности исполнения каждого из-за их различного дизайна. Вы должны ожидать этого поведения в любом случае.
Я просто не понимаю, почему он будет работать для всех остальных.
blockquote>Это не так. Будьте героем своего класса и объясните, как он работает и как его исправить. Скажите им, что они посылают свою любовь. :)
Как уже объяснялось, предположение о том, что printf()
является атомарным и не будет искажать ваш результат, тогда как std::cout::operator<<()
не является и будет испортить вещи, если они в корне неверны.
Однако все еще существует (крошечная) часть «истины» в этом, но на другом уровне. Позвольте мне привести вам пример:
Если я попытаюсь использовать C-стиль OpenMP «Hello world», который может дать это:
printf( "Hello from thread %d of %d\n",
omp_get_thread_num(),
omp_get_num_threads() );
Тот же самый стиль C ++ может выглядеть например:
std::cout << "Hello from thread " << omp_get_thread_num()
<< " of " << omp_get_num_threads()
<< std::endl;
И существенное различие между ними заключается в том, что для printf()
я вызываю только метод печати один раз, с полностью подготовленной выходной строкой, тогда как в стиле C ++ std::cout::operator<<()
5 раз, только с битами и частями строк, которые могут быть отправлены или не отправлены на стандартный вывод. Внутри все может случиться, и я не буду пытаться совершать какие-либо действия. Но, по крайней мере, используя здесь printf()
, я увеличиваю свои шансы на чистый вывод, даже если я не могу этого гарантировать.
Вот полный пример:
#include <iostream>
#include <stdio.h>
#include <omp.h>
int main() {
#pragma omp parallel
printf( "Hello from thread %d of %d with printf()\n",
omp_get_thread_num(),
omp_get_num_threads() );
printf( "*** outside of parallel region ***\n" );
#pragma omp parallel
std::cout << "Hello from thread " << omp_get_thread_num()
<< " of " << omp_get_num_threads()
<< " with std::cout"
<< std::endl;
return 0;
}
Какой на моем Linux-ноутбуке дает мне (GCC 5.2):
~/tmp$ g++ -fopenmp stdout.cc
~/tmp$ ./a.out
Hello from thread 3 of 4 with printf()
Hello from thread 0 of 4 with printf()
Hello from thread 2 of 4 with printf()
Hello from thread 1 of 4 with printf()
*** outside of parallel region ***
Hello from thread Hello from thread Hello from thread Hello from thread 1 of 4 with std::cout23 of 4 with std::cout
of 4 with std::cout
0 of 4 with std::cout
~/tmp$
Если вы внимательно посмотрите, вы увидите, что ни один из индивидуальных звонков на std::cout::operator<<()
не разбит, но каждый новый вызов - это возможность для различные потоки, чтобы разыгрывать друг друга, и получить выход из строя.
Итак, опять же, говоря, что printf()
является атомарным и не испортит вещи, неправильно, но просто для сложного вывода string, он вряд ли будет искажен, чем с std::cout
.