Вывод значений массива, получить 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
В этом примере класса не хватает конструкторов копирования и/или перемещения и, соответственно копирующего и/или перемещающего оператора присваивания. Вы можете попробовать написать их самостоятельно и, если возникнут трудности, задать соответствующий вопрос на форуме.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Какие существуют виды рекламных бордов и как выбрать подходящий?
Недавно столкнулся с одной непонятной для меня вещью - указатели на функции классаИмеют ли они смысл ? В каких случаях используются ? Пример:
Как в SQL-запросе подставить в название колонки значения, которые находятся в ней?
Как взять все данные из таблицы в БД и отправить их в Excel (сделать отчет)?