Вывод значений массива, получить 4 элемента по очереди, результат
1.000000 0.000000 -nan -nan 0.000000
отличается от ожидаемого
class DataSrc{
int current_position;
int dlina;
double * curent_elem;
public:
DataSrc(){
current_position=0;
dlina=4;
double histori[]={1, 2, 3, 7, 6, 2, 4, 3, 2};
curent_elem=&histori[0];
}
double * GetNext(){
if(current_position>dlina){
return 0;
}
current_position++;
return curent_elem+current_position-1;
}
};
int main(){
DataSrc MyData;
double *eee=MyData.GetNext();
while(eee){
printf(" %lf ",*eee);
eee=MyData.GetNext();
}
return 0;
}
Как сделать правильно, почему популярный совет из учебников о получении следующего значения "адрес++" здесь не работает?
Потому что вы создали локальный массив histori, который после выхода из конструктора уничтожается, и храните указатель в фиг куда...
Если хочется, чтоб работало - то, например, так:
class DataSrc
{
int current_position;
int dlina;
double * curent_elem;
double * histori;
public:
DataSrc()
{
histori = new double[9]{1, 2, 3, 7, 6, 2, 4, 3, 2};
current_position = 0;
dlina = 4;
curent_elem = &histori[0];
}
~DataSrc()
{
delete[] histori;
}
double * GetNext()
{
if(current_position>dlina) return 0;
return curent_elem+current_position++;
}
};
int main()
{
DataSrc MyData;
double *eee=MyData.GetNext();
while(eee){
printf(" %lf ",*eee);
eee=MyData.GetNext();
}
return 0;
}
(вопрос о том, как написать так, чтобы не просто работало, но и имело смысл, пока не рассматриваем).
Как уже было отмечено, данное объявление в конструкторе класса
DataSrc(){
current_position=0;
dlina=4;
double histori[]={1, 2, 3, 7, 6, 2, 4, 3, 2};
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
curent_elem=&histori[0];
}
является объявлением локального массива с автоматической продолжительностью хранения. То есть время жизни этого массива завершается после выхода из конструктора. Поэтому обращение к этому массиву вне тела конструктора ведет к неопределенному поведению программы.
Чтобы иметь возможность обращаться периодически к некоторому массиву из методов класса, следует сделать этот массив членом класса.
У вас в классе имеется некоторая избыточность в объявлениях членов данных класса. Из этих двух членов класса
int current_position;
double * curent_elem;
достаточно иметь лишь один член класса current_position, так как второй член класса curent_elem всегда можно получить, имея первый член класса.
Инициализировать массив-член класса можно, передав конструктору указатель на первый элемент некоторого массива, используемого в качестве аргумента, и его размер. Либо можно в качестве параметра использовать список инициализации.
Также в минимальный набор методов класса желательно включить метод, который устанавливает в исходное значение член данных current_position, или проще его назвать как position.
Ниже приведен некоторый каркас класса, который можно развивать далее, наращивая его методы. В этом примере используется стандартный класс std::unique_ptr. Чем раньше вы начнете использовать стандартные средства из библиотеки C++, тем скорей вы к ним привыкните и освоите.
#include <iostream>
#include <memory>
#include <initializer_list>
#include <algorithm>
template <typename T>
class DataSrc
{
private:
size_t n;
std::unique_ptr<T[]> p;
mutable size_t position;
public:
DataSrc() : n( 0 ), p( nullptr ), position( 0 )
{
}
DataSrc( const T *p, size_t n ) : n( n ), p( new T[n] ), position( 0 )
{
std::copy( p, p + n, DataSrc::p.get() );
}
DataSrc( std::initializer_list<T> lst ) : n( lst.size() ), p( new T[lst.size()] ), position( 0 )
{
std::copy( lst.begin(), lst.end(), DataSrc::p.get() );
}
size_t size() const
{
return n;
}
const T * GetNext() const
{
return position == n ? nullptr : p.get() + position++;
}
T * GetNext()
{
return position == n ? nullptr : p.get() + position++;
}
void Reset()
{
position = 0;
}
void Reset() const
{
position = 0;
}
};
int main()
{
int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, };
DataSrc<int> data1( a, sizeof( a ) / sizeof( *a ) );
while ( int *current = data1.GetNext() ) std::cout << *current << ' ';
std::cout << std::endl;
DataSrc<int> data2( { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, } );
while ( int *current = data2.GetNext() ) std::cout << *current << ' ';
std::cout << std::endl;
data2.Reset();
while ( int *current = data2.GetNext() ) std::cout << *current << ' ';
std::cout << std::endl;
return 0;
}
Вывод программы на консоль
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
В этом примере класса не хватает конструкторов копирования и/или перемещения и, соответственно копирующего и/или перемещающего оператора присваивания. Вы можете попробовать написать их самостоятельно и, если возникнут трудности, задать соответствующий вопрос на форуме.
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости