c ++传递ptrs

时间:2014-11-25 19:57:34

标签: c++ pointers unique-ptr

仍然有很多问题掌握指针,我试图不使用它们,但我不知道如何最好地完成以下操作。

我有两个类PointRay,我也确定可能已经有一个我应该使用的点类的实现。所以我有这两个类,我正在尝试创建一个光线,并最终将其传递给其他东西,但我收到一个错误: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 个答案:

答案 0 :(得分:4)

我相信这应该可行 - 我只是从代码中删除了所有指针并改为使用实例。在你的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;
}

希望这会让你开始。祝其他任务好运!

答案 1 :(得分:0)

您的代码有两个问题:导致您遇到崩溃的第一个问题是,Ray构造函数中的分配是noops。在行

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<>:第一个是名为unique_ptr<>的{​​{1}},第二个是类point中名为unique_ptr<>的{​​{1}}。因此,您的程序会尝试销毁origin对象两次,一次是变量Ray超出范围,第二次是变量Point超出范围。

当使用标准C ++库“智能”指针时,永远不要将智能指针转换为裸指针/引用,然后从该裸指针/引用重新创建智能指针。只要您只通过智能指针分配智能指针或通过引用传递智能指针,您就是安全的,但是您必须永远不要为同一个对象创建两个彼此不了解的智能指针。即使使用point,也绝对不能这样做。如果你这样做,他们都会尝试做他们的工作,你会崩溃(希望如此)。


旁注(只是我2美分的偏见):
我相信指针最好不是通过使用C ++及其“智能”指针来理解,而是通过使用旧样式编写程序,使用C. C形指针的裸指针实际上是非常简单,非常强大,尽管非常危险。他们需要一些经验才能掌握。首先要了解以安全的方式使用裸指针需要做些什么;一旦你能做到这一点,你将拥有在睡眠中使用智能指针的所有必要的理解。