С ++ прохождение ptrs
У меня все еще много проблем с захватом указателей, я пытался их не использовать, но я не уверен, как лучше всего выполнить следующее.
У меня два класса Point
а также Ray
Я также уверен, что где-то уже есть реализация класса точек, который я должен использовать вместо этого. Итак, у меня есть эти два класса, и я пытаюсь создать луч и в конечном итоге передать его чему-то другому, но я получаю ошибку: Thread
: EXC_BAD_ACCESS (code = 1, address = 0x0) `когда я создаю луч так, как я это делаю, и пытаюсь получить к нему доступ.
class Point {
public:
float x;
float y;
Point();
Point(float x, float y);
~Point();
};
Point::Point() {
x = 0;
y = 0;
}
Point::Point(float xPos, float yPos) {
x = xPos;
y = yPos;
std::cout << "point created at: " << x << ", " << y << std::endl;
}
Point::~Point() {
std::cout << "point destroyed" << std::endl;
}
class Ray {
public:
std::unique_ptr<Point> origin;
float angleInRadians;
float length;
float slope();
Point* pointAtDistance(float percentage);
Point* pointAtYPos(float yPos);
Ray(Point& origin, float angleInRadians, float length);
~Ray();
};
Ray::Ray(Point& origin, float angleInRadians, float length) {
origin = std::move(origin);
angleInRadians = angleInRadians;
length = length;
}
float Ray::slope() {
return tanf(angleInRadians);
}
Point* Ray::pointAtDistance(float percentage) {
return new Point(origin->x + (length * percentage) * cosf(angleInRadians), origin->y + (length * percentage) * sinf(angleInRadians));
}
Point* Ray::pointAtYPos(float yPos) {
float B = origin->y - (slope() * origin->x);
return new Point((yPos - B) / slope(), yPos);
}
Ray::~Ray() {
std::cout << "point released" << std::endl;
origin.release();
std::cout << "ray destroyed" << std::endl;
}
Третья строка, где появляется ошибка.
std::unique_ptr<Point> point(new Point(x,y));
std::unique_ptr<Ray> ray(new Ray(*point, M_PI/4, 100));
std::cout << "RAY origin: " << ray->origin->x << ", " << ray->origin->y << std::endl;
2 ответа
Я считаю, что это должно сработать - я буквально удалил все указатели из вашего кода и использовал вместо них экземпляры. На вашем уровне знаний C++, указатели почти всегда не нужны.
class Point {
public:
Point();
Point(float x, float y);
~Point();
float x;
float y;
};
Point::Point() {
x = 0;
y = 0;
}
Point::Point(float xPos, float yPos) : x(xPos), y(yPos) {
std::cout << "point created at: " << x << ", " << y << std::endl;
}
Point::~Point() {
std::cout << "point destroyed" << std::endl;
}
class Ray {
public:
Ray(const Point& origin, float angleInRadians, float length);
~Ray();
float slope();
Point pointAtDistance(float percentage);
Point pointAtYPos(float yPos);
Point origin;
float angleInRadians;
float length;
};
Ray::Ray(const Point& o, float a, float l) : origin(o), angleInRadians(a), length(l) {
}
float Ray::slope() {
return tanf(angleInRadians);
}
Point Ray::pointAtDistance(float percentage) {
return Point(origin.x + (length * percentage) * cosf(angleInRadians), origin.y + (length * percentage) * sinf(angleInRadians));
}
Point Ray::pointAtYPos(float yPos) {
float B = origin.y - (slope() * origin.x);
return Point((yPos - B) / slope(), yPos);
}
Ray::~Ray() {
std::cout << "ray destroyed" << std::endl;
}
Надеюсь, это поможет вам начать. Удачи с остальным заданием!
В вашем коде есть две проблемы: первая проблема, которая приводит к сбою, который вы испытываете, заключается в том, что ваши назначения в Ray
конструктор нупс. В соответствии
origin = std::move(origin);
оба случая origin
ссылаются на одну и ту же переменную (которая является локальной для функции). Следовательно, переменные в вашем классе остаются un/default-initialized. Для интеллектуального указателя инициализация по умолчанию означает, что он содержит указатель NULL, который вызывает ошибки при обращении к нему.
Тем не менее, изменение вашего конструктора для использования списков инициализатора, что позволяет избежать этой проблемы
Ray::Ray(Point& origin, float angleInRadians, float length) :
origin(&origin), angleInRadians(angleInRadians), length(length)
{}
не удалит сбой из-за второй проблемы в вашем коде: вы создаете два разных unique_ptr<>
s для того же объекта: первый unique_ptr<>
называется point
второй unique_ptr<>
называется origin
в классе Ray
, Итак, ваша программа пытается уничтожить Point
объект дважды, один раз, когда переменная point
выходит из области видимости, второй, когда переменная ray
выходит за рамки.
При использовании "умных" указателей стандартных библиотек C++ крайне важно никогда не преобразовывать умный указатель в пустой указатель / ссылку, а затем воссоздавать умный указатель из этого открытого указателя / ссылки. Вы в безопасности, если только назначаете умные указатели из умных указателей или передаете умные указатели по ссылке, но вы никогда не должны создавать два умных указателя, которые не знают друг друга для одного и того же объекта. Даже с shared_ptr<>
это никогда не должно быть сделано. Если вы это сделаете, оба попытаются выполнить свою работу, и вы получите крах (надеюсь).
Sidenote (только мои 2 цента пристрастной мудрости):
Я полагаю, что указатели лучше всего понимаются не с использованием C++ и его "умных" указателей, а с помощью написания программ, использующих старый стиль, обнаженные указатели на C-стиле в действительности являются очень простой, очень мощной, хотя и довольно опасной вещью. И им нужен некоторый опыт, чтобы освоить. Сначала узнайте, что нужно сделать, чтобы безопасно использовать голые указатели; Как только вы это сделаете, у вас будет все необходимое понимание, чтобы использовать умные указатели во сне.