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

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 9, средняя оценка - 4.78
Somebody
2777 / 1591 / 142
Регистрация: 03.12.2007
Сообщений: 4,170
Завершенные тесты: 1
#1

Непонятное поведение std::valarray - C++

05.11.2010, 16:51. Просмотров 1146. Ответов 9
Метки нет (Все метки)

Есть такой код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include <valarray>
 
using namespace std;
 
int main()
{
    valarray<int> a(2);
    a[0] = 2; a[1] = 1;
    a = a[0] * a;
    cout << a[0] << ' ' << a[1] << endl;
    cin.peek();
}
Если компилировать Borland'ом, выводит интуитивно понятное 4 2, а если g++, то 4 4. Если было бы
C++
1
a *= a[0];
то a[0] передаётся по ссылке, undefined behaviour. Но здесь же вроде должен создаваться временный valarray, из которого потом копируется в a. Sequence point'ы есть до и после вызова operator* и operator=. Но это всё равно выполняется как
C++
1
2
a[0] = a[0] * a[0];
a[1] = a[0] * a[1];
Что бы это всё могло значить?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
05.11.2010, 16:51     Непонятное поведение std::valarray
Посмотрите здесь:

Странное рекурсивное поведение объекта std::cout C++
Непонятное поведение list, vector в другом классе C++
Непонятное поведение простой функции C++
Непонятное поведение C++
C++ Непонятное поведение простейшей формулы
C++ Непонятное поведение программы
C++ Непонятное поведение потока ввода: в одной функции букву ввёл = во всех функциях наперёд ввёл. Распродажа!
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
volovzi
267 / 169 / 8
Регистрация: 14.03.2010
Сообщений: 501
06.11.2010, 02:49     Непонятное поведение std::valarray #2
Somebody, ну да, в оператор умножения объекты передаются по ссылке, а умножение происходит последовательно, поэтому сначала умножается a[0] на a[0]. После этого a[0] == 4. А затем a[1] == 1 умножается на новое a[0], которое уже равно четырём.
Если ты умножишь массив на константу, то всё посчитается так, как и должно быть интуитивно.

Если же тебе неохото заводить новую переменную, то пиши так:
C++
1
a = a * int(a[0]);
Somebody
2777 / 1591 / 142
Регистрация: 03.12.2007
Сообщений: 4,170
Завершенные тесты: 1
06.11.2010, 12:24  [ТС]     Непонятное поведение std::valarray #3
Цитата Сообщение от volovzi Посмотреть сообщение
в оператор умножения объекты передаются по ссылке, а умножение происходит последовательно, поэтому сначала умножается a[0] на a[0]. После этого a[0] == 4.
Так operator* должен же возвращать временный объект, а потом уже из него копируется в a?
volovzi
267 / 169 / 8
Регистрация: 14.03.2010
Сообщений: 501
06.11.2010, 12:34     Непонятное поведение std::valarray #4
Верно. Но в процессе умножения массив (а именно элемент a[0]) модифицируется. Почему — я объяснил в предыдущем сообщении.
Somebody
2777 / 1591 / 142
Регистрация: 03.12.2007
Сообщений: 4,170
Завершенные тесты: 1
06.11.2010, 18:48  [ТС]     Непонятное поведение std::valarray #5
С какого он модифицируется, если он передаётся по константной ссылке?
Код
template <class T> valarray<T> operator* (const T& val, const valarray<T>& rhs);
Ладно, тогда что из следующего верно:
1) Правильный ответ 4 4. В Borland C++ 5.5.1 баг.
2) Правильного ответа нет, потому что undefined behaviour. Тогда по какому пункту стандарта оно?
volovzi
267 / 169 / 8
Регистрация: 14.03.2010
Сообщений: 501
06.11.2010, 19:05     Непонятное поведение std::valarray #6
Да, действительно, ссылка константная. Мне сначала показалось, что нет.
В таком случае, наверное, глюк gcc.

Возможно, в реализации там сначала умножается исходный массив, а потом меняется местами с новым.
В любом случае, константность ссылки это не отменяет, поэтому, действительно, очень странно.
kravam
быдлокодер
1690 / 877 / 44
Регистрация: 04.06.2008
Сообщений: 5,395
07.11.2010, 00:50     Непонятное поведение std::valarray #7
Somebody, скажите пожалуйста, а что Вы делаете этой строкой?


Цитата Сообщение от Somebody Посмотреть сообщение
valarray <int>a(2);
Я тут порылся, но
аналогов не нашёл
volovzi
267 / 169 / 8
Регистрация: 14.03.2010
Сообщений: 501
07.11.2010, 08:49     Непонятное поведение std::valarray #8
kravam, см. второй конструктор по твоей же ссылке.
Somebody
2777 / 1591 / 142
Регистрация: 03.12.2007
Сообщений: 4,170
Завершенные тесты: 1
10.01.2013, 17:36  [ТС]     Непонятное поведение std::valarray #9
Всплыла тут эта тема... В стандарте есть такая фраза: "The valarray array classes are defined to be free of certain forms of aliasing, thus allowing operations on these classes to be optimized". В общем, идея valarray'ев такая:
http://en.cppreference.com/w/cpp/numeric/valarray
std::valarray and helper classes are defined to be free of certain forms of aliasing, thus allowing operations on these classes to be optimized similar to the effect of the keyword restrict in the C programming language. In addition, functions and operators that take valarray arguments are allowed to return proxy objects to make it possible for the compiler to optimize an expression such as v1 = a*v2 + v3; as a single loop that executes v1[i] = a*v2[i] + v3[i]; avoiding any temporaries or multiple passes...
Так что, думаю, g++ сделал всё нормально. Но точного определения этих "certain forms of aliasing" я так в стандарте не нашёл.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
10.01.2013, 20:14     Непонятное поведение std::valarray
Еще ссылки по теме:

Странное поведение операции XOR и std::cin C++
C++ Непонятное поведение программы
C++ Шаблонный класс с шаблонным оператором внутри - непонятное поведение
Объяснить поведение объекта std::cin в цикле while C++
C++ Непонятное мне поведение функции

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
diagon
Higher
1924 / 1190 / 49
Регистрация: 02.05.2010
Сообщений: 2,925
Записей в блоге: 2
10.01.2013, 20:14     Непонятное поведение std::valarray #10
В стандарте (955 страница) есть такой пункт.
If the value of an element in the left-hand side of a valarray assignment operator depends on the value
of another element in that left-hand side, the resulting behavior is undefined.
Как-то мутно написано, но вроде подходит под ваш случай.
Проблема именно в присваивании, ибо a[0] * a вычисляется вполне корректно, а вот если в левую часть присваивания поставить другой valarray, то будет 4 2.
Yandex
Объявления
10.01.2013, 20:14     Непонятное поведение std::valarray
Ответ Создать тему
Опции темы

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