Форум программистов, компьютерный форум CyberForum.ru

Вывод в cout - C++

Восстановить пароль Регистрация
 
snorlax212
2 / 2 / 0
Регистрация: 03.03.2013
Сообщений: 17
22.03.2013, 22:39     Вывод в cout #1
Добрый вечер. Есть код:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <iostream>
using namespace std;
 
class queue {
    int q[100];
    int sloc, rloc;
public:
    void init();
    void qput(int i);
    int qget();
};
 
void queue::init() {
    rloc = sloc = 0;
}
 
void queue::qput(int i) {
    if (sloc == 100) {
        cout << "Очередь заполнена." << endl;
        return;
    }
    sloc++;
    q[sloc] = i;
}
 
int queue::qget() {
    if (rloc == sloc) {
        cout << "Очередь пуста." << endl;
        return 0;
    }
    rloc++;
    return q[rloc];
}
 
void main() {
    queue a, b;
    a.init(); 
    b.init();
    a.qput(10); 
    b.qput(19); 
    a.qput(20);
    b.qput(1);
    cout << "Содержимое очереди a: ";
    cout << a.qget() << ' ';
    cout << a.qget() << endl;
    cout << "Содержимое очереди b: ";
    cout << b.qget() << ' ';
        cout << b.qget() << endl;
}
Вопрос: почему, когда я пишу вывод элементов очереди в две строки
C++
1
2
cout << a.qget() << ' ';
cout << a.qget() << endl;
, то выводится как надо, по порядку. А если в один поток
C++
1
cout << a.qget() << ' ' << a.qget() << endl;
, то сначала последний элемент, а потом первый? В чём разница?
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Байт
 Аватар для Байт
13974 / 8805 / 1227
Регистрация: 24.12.2010
Сообщений: 15,949
22.03.2013, 23:10     Вывод в cout #2
Цитата Сообщение от snorlax212 Посмотреть сообщение
сначала последний элемент, а потом первый? В чём разница?
Выражение анализируется с конца. В стек попадают сначала последние аргументы. А потом они снимаются с верхушки стека. То. что у тебя происходит, называется побочный эффект Если тебе эти слова ничего не говорят, постарайся избегать подобных выражений. Если все-таки интересно, посмотри как перегружена операция "<<" в соответствующем классе и узнай, как происходит передача параметров в функцию на ассемблерном уровне.
Kastaneda
Модератор
Эксперт С++
 Аватар для Kastaneda
4236 / 2769 / 218
Регистрация: 12.12.2009
Сообщений: 7,104
Записей в блоге: 1
Завершенные тесты: 1
22.03.2013, 23:13     Вывод в cout #3
Недавно обсуждалось. В общем это UB (undefined behavior), т.е. на другом компиляторе может работать так, как задумывалось. Но уповать на компилятор не стОит, поэтому подобных вещей лучше избегать.
snorlax212
2 / 2 / 0
Регистрация: 03.03.2013
Сообщений: 17
22.03.2013, 23:20  [ТС]     Вывод в cout #4
Байт, Kastaneda, понял, спасибо.
Байт
 Аватар для Байт
13974 / 8805 / 1227
Регистрация: 24.12.2010
Сообщений: 15,949
22.03.2013, 23:29     Вывод в cout #5
Цитата Сообщение от Kastaneda Посмотреть сообщение
В общем это UB (undefined behavior), т.е. на другом компиляторе может работать так, как задумывалось.
Абсолютной уверенности нет, я не большой знаток стандартов, но мне кажется, что засовывание параметров в стек справа налево есть именно фишка языка Си со времен K&R. Что позволяет естественно работать с функциями с переменным числом параметров типа printf. И если не предпринимать специальных телодвижений типа fastcall, _PASCAL_, то во всех Си и Си++ компиляторах это так и будет происходить. Если я не прав, пусть товарищи меня поправят.
Цитата Сообщение от Kastaneda Посмотреть сообщение
подобных вещей лучше избегать.
А вот тут я полностью с вами согласен
Kastaneda
Модератор
Эксперт С++
 Аватар для Kastaneda
4236 / 2769 / 218
Регистрация: 12.12.2009
Сообщений: 7,104
Записей в блоге: 1
Завершенные тесты: 1
23.03.2013, 00:02     Вывод в cout #6
Цитата Сообщение от Байт Посмотреть сообщение
что засовывание параметров в стек справа налево
Не, тут дело не в этом. Дело в том, что нельзя с уверенностью сказать какой параметр функции будет вычислен первым.
Например
C++
1
2
3
4
5
6
int i = 0;
int f1() {return i++;}
int f2() {return i++;}
int func(int a, int b) {}
 
func (f1(), f2()); // вызов
здесь нельзя утвержать, что f1() вызовется раньше f2(), поэтому аргументы func могут отличаться в зависимости от компилятора.

Тут тоже самое, вот этот код
C++
1
cout << a.qget() << ' ' << a.qget() << endl;
на самом деле выглядет так
C++
1
operator << (operator << (operator << (operator << (cout, a.qget()), ' '), a.qget()), endl);// надеюсь со скобками не напутал)
и здесь мы можем быть уверены только в порядке вызова операторов и в том, что к моменту из вызова аргументы будут вычислены. Но в каком порядке будут вычислятся аргументы мы сказать не можем, т.е. какой из qget() когда будет вызван - хз.

clang компилирует из этого код с ожидаемым поведением.
Yandex
Объявления
23.03.2013, 00:02     Вывод в cout
Ответ Создать тему
Опции темы

Текущее время: 23:10. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru