Возврат ссылки на элемент контейнера члена класса
Foo ведет себя как круговой итератор. Несмотря на то, что я нервничаю по этому поводу, приведенный ниже код компилируется нормально, но создает ошибку во время выполнения. Я получаю сообщение об ошибке, даже если удаляю константы из get_current(). Конечно, я могу вернуть указатель, и он будет работать; однако получу ли я лучшую безопасность, возвращая ссылку?
#include <iostream>
#include <array>
#include <memory>
class Foo
{
public:
Foo();
void next();
const int& get_current() const;
private:
std::array<std::unique_ptr<int>, 3> arr_;
unsigned i_;
};
Foo::Foo() : i_(0)
{
arr_[0] = std::unique_ptr<int>(new int(5));
arr_[1] = std::unique_ptr<int>(new int(6));
arr_[2] = std::unique_ptr<int>(new int(7));
}
void Foo::next()
{
++i_;
i_ %= 3;
}
const int& Foo::get_current() const
{
return *arr_[i_];
}
int main()
{
Foo foo;
int* p;
*p = foo.get_current();
//do something with p
std::cout << *p << std::endl;
foo.next();
*p = foo.get_current();
//do something with p
std::cout << *p << std::endl;
return 0;
}
3 ответа
int* p;
Это неинициализированный указатель, не указывающий ни на что. Разыменование дает неопределенное поведение.
*p = foo.get_current();
Это разыменовывает неверный указатель. Boom!
Возможно, вы хотите, чтобы он указывал на элемент массива
p = &foo.get_current();
или, возможно, вы хотите копию элемента массива
int n;
n = foo.get_current();
foo.get_current();
вполне может быть возвращение const
ссылка, но после этого вы пытаетесь получить значение копии этого при назначении *p
,
Назначение *p
это то, что вызывает у вас проблемы, как p
неинициализирован. Это неопределенное поведение, которое в вашем случае проявляется как ошибка времени выполнения.
Вы можете использовать код как const int& p = foo.get_current();
но имейте в виду, что ссылку можно связать только один раз, поэтому вам нужно быть осторожным с областью видимости.
Или вы можете использовать std::shared_ptr<int>
и сделать это тип возврата get_current()
и полностью лишить ваш код голых указателей.
*p = ...
Вы разыменование int* P
без надлежащей инициализации.
Измените свой код в главном на
int p; // Remove *
p = foo.get_current();
//do something with p
std::cout << p << std::endl;
или если вы действительно хотели использовать указатель
const int* p;
p = &foo.get_current();
// ^ Take the address