переменные экземпляра — std :: vector pushback генерирует EXC_BAD_ACCESS при использовании внутри статического метода C ++

У меня есть класс Foo со статическим фабричным методом — Foo :: createOne — который создает экземпляр и помещает некоторые данные в закрытую переменную-член типа std: vector. Когда я вызываю Foo :: createOne, моя программа выдает это исключение: «EXC_BAD_ACCESS (не удалось получить доступ к памяти)»

Вот код:

foo.h

#include <vector>

class Foo {
public:
Foo();
Foo(const Foo& orig);
virtual ~Foo();

static Foo * createOne();

private:
std::vector<int> v;

};

foo.cpp

#include "Foo.h"
Foo::Foo() {
};

Foo::Foo(const Foo& orig) {
};

Foo::~Foo() {
};

Foo * Foo::createOne() {
Foo *f;
f->v.push_back(5);
return f;
}

main.cpp

#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;
}

1

Решение

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 выйдет из памяти, когда функция завершится, и указатель на нее будет также неопределенным поведением.

2

Другие решения

Вы должны создать экземпляр Foo перед его использованием.
На куче вы можете использовать следующие

Foo *f = new Foo();
2

Вы разыменовываете указатель, который не был инициализирован:

Foo *f;  // f not pointing to a Foo instance
f->v.push_back(5);

Это неопределенное поведение. Вы должны сделать f указать на действительный Foo объект.

1

В 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;

}
1
По вопросам рекламы [email protected]