У меня есть класс Foo со статическим фабричным методом — Foo :: createOne — который создает экземпляр и помещает некоторые данные в закрытую переменную-член типа std: vector. Когда я вызываю Foo :: createOne, моя программа выдает это исключение: «EXC_BAD_ACCESS (не удалось получить доступ к памяти)»
Вот код:
#include <vector>
class Foo {
public:
Foo();
Foo(const Foo& orig);
virtual ~Foo();
static Foo * createOne();
private:
std::vector<int> v;
};
#include "Foo.h"
Foo::Foo() {
};
Foo::Foo(const Foo& orig) {
};
Foo::~Foo() {
};
Foo * Foo::createOne() {
Foo *f;
f->v.push_back(5);
return f;
}
#include <iostream>
#include "Foo.h"
int main(int argc, char** argv) {
std::cout << "Testing createOne." << std::endl;
Foo *myFoo = Foo::createOne();
std::cout << "It worked." << std::endl;
}
Спасибо за ответы. Я исправил проблему неинициализированного указателя (ниже). Теперь я получаю предупреждение компилятора «адрес локальной переменной ‘f’ возвращен»
Foo * Foo::createOne() {
Foo f;
f.v.push_back(5);
return &f;
}
Foo *f;
f->v.push_back(5);
Первая строка создает необработанный неинициализированный указатель. Это не экземпляр переменной, поэтому попытка разыменовать его Неопределенное поведение.
Вам нужно инициализировать его экземпляром, например так:
Foo *f = new Foo();
f->v.push_back(5);
// ...
delete f;
Только тогда ваш код станет действительным.
Обновление: после просмотра вашего кода еще раз я понимаю, что использование указателей совершенно не нужно. Вы можете сделать то же самое, вернув по значению:
Foo Foo::createOne()
{
Foo f;
f.v.push_back(5);
return f;
}
Причина, по которой вы получили ошибку address of local variable f returned
потому что вы возвращали указатель на временное значение. Локальная переменная f
выйдет из памяти, когда функция завершится, и указатель на нее будет также неопределенным поведением.
Вы должны создать экземпляр Foo перед его использованием.
На куче вы можете использовать следующие
Foo *f = new Foo();
Вы разыменовываете указатель, который не был инициализирован:
Foo *f; // f not pointing to a Foo instance
f->v.push_back(5);
Это неопределенное поведение. Вы должны сделать f
указать на действительный Foo
объект.
В C ++, когда вы объявляете указатель, конструктор должен вызываться вручную, например так:
Foo * Foo::createOne() {
Foo *f = new Foo; // <<=== Here
f->v.push_back(5);
return f;
}
Это отличается от объектов, определенных как объекты, а не как указатели:
Foo Foo::createOne() {
Foo f; // No initializer is necessary
f.v.push_back(5);
return f;
}
В этом случае объект возвращается по значению, поэтому его содержимое копируется в процессе.
Когда вы создаете объекты динамически, объект, на который указывает указатель, должен быть удален, чтобы избежать утечек памяти, например:
int main(int argc, char** argv) {
std::cout << "Testing createOne." << std::endl;
Foo *myFoo = Foo::createOne();
std::cout << "It worked." << std::endl;
delete myFoo;
}