Если вы используете g ++, у вас есть свисающая ссылка, которая ведет к неопределенному поведению, и cra sh.
Это ошибка в g ++.
В этой строке:
std::gslice_array<int> g = v[get_block(3)];
путем вызова get_block(3)
создается временный экземпляр gslice
. Метод valarray::operator[](gslice)
вызывается с использованием этого временного gslice
. Давайте посмотрим на его реализацию:
template<typename _Tp>
inline gslice_array<_Tp>
valarray<_Tp>::operator[](const gslice& __gs)
{
return gslice_array<_Tp> (_Array<_Tp>(_M_data), __gs._M_index->_M_index);
}
он принимает ссылку на const gslice
, поэтому временный экземпляр gslice
может быть связан с __gs
, при возврате из этого метода объект gslice_array
создается:
template<typename _Tp>
inline
gslice_array<_Tp>::gslice_array(_Array<_Tp> __a,
const valarray<size_t>& __i)
: _M_array(__a), _M_index(__i) {}
, где _M_array
и _M_index
из gslice_array
определены как:
_Array<_Tp> _M_array;
const valarray<size_t>& _M_index; // <------------- here is reference !
Для _M_index
из gslice_array
назначено __gs._M_index->_M_index
, Что такое __gs._M_index
? Это внутренняя структура gslice
с именем _Indexer
. Он использует механизм счетчика ссылок, чтобы продлить саму жизнь. Счетчик ссылок _Indexer
может быть увеличен только в том случае, если копируется gslice
(конструктором копирования или оператором назначения копирования), но ни одна из этих операций не выполняется в этом коде. Следовательно, когда gslice
как временный объект удаляется, _M_index
из __gs
также удаляется, и, наконец, появляется свисающая ссылка.
Где ошибка? Сохранение ссылки на член индексатора, который удаляется при удалении gslice
. Этого бы не произошло, если бы индексатор содержал указатель на valarray вместо ссылки. Хранение ссылок не является переходным.
В качестве обходного пути, создайте экземпляр значения L gslice
следующим образом:
auto b = get_block(3);
std::gslice_array<int> g = v[b];
g = 3;
print();
, тогда все работает нормально.