Вектор push_back изменяет значения предыдущих элементов. - PullRequest
0 голосов
/ 26 ноября 2018

Использование вектора в функции-члене getPoints () демонстрирует странное поведение.

После помещения новых объектов в вектор предыдущим объектам присваивается новое значение.

И когда возвращается вектор, я получаю значения мусора.

Вектор не хранит и не использует ссылочные переменные.

Может кто-нибудь объяснить, что происходит.

Спасибо.

КОД

#include<iostream>
#include<vector>
#include<math.h>

using namespace std;


class Unit{
public:

    double n[2];
    double &x = n[0], &y = n[1];

    Unit(double x=0, double y=0){
        n[0] = x;
        n[1] = y;
    }

    Unit& operator=(const Unit& rhs){
        this->x = rhs.x;
        this->y = rhs.y;
        return *this;
    }

    Unit& operator+=(const Unit& rhs){
        this->x += rhs.x;
        this->y += rhs.y;
        return *this;
    }

    Unit operator+(const Unit& rhs){
        return Unit(x+rhs.x, y+rhs.y);
    }

    Unit& operator-=(const Unit& rhs){
        this->x -= rhs.x;
        this->y -= rhs.y;
        return *this;
    }

    Unit operator-(const Unit& rhs){
        return Unit(x-rhs.x, y-rhs.y);
    }

    Unit& operator*=(const Unit& rhs){
        this->x *= rhs.x;
        this->y *= rhs.y;
        return *this;
    }

    Unit operator*(const Unit& rhs){
        return Unit(x*rhs.x, y*rhs.y);
    }

    Unit operator*=(double rhs){
        this->x *= rhs;
        this->y *= rhs;
        return *this;
    }

    Unit operator*(double rhs){
        return Unit(x*rhs, y*rhs);
    }

    Unit operator/=(const Unit& rhs){
        this->x /= rhs.x;
        this->y /= rhs.y;
        return *this;
    }

    Unit operator/(const Unit& rhs){
        return Unit(x/rhs.x, y/rhs.y);
    }

    Unit operator/=(double rhs){
        this->x /= rhs;
        this->y /= rhs;
        return *this;
    }

    Unit operator/(double rhs){
        return Unit(x/rhs, y/rhs);
    }

    double dot(const Unit& rhs){
        return x * rhs.x + y * rhs.y;
    }

    double len2(){
        return dot(*this);
    }

    double len(){
        return sqrt(len2());
    }

    double distance2(const Unit& rhs){
        Unit C = *this - rhs;
        return C.len2();
    }

    double distance(const Unit& rhs){
        return sqrt(distance2(rhs));
    }

    Unit Normalize(){ 
        return *this * 1.0 / len(); 
    }

    Unit Round(){
        return Unit(round(x), round(y));
    }

    Unit Trunc(){
        return Unit(int(x), int(y));
    }

    vector<Unit> getPoints(const Unit& rhs){

        vector<Unit> points;

        Unit start, end;

        if(x < rhs.x){

            start = *this;
            end = rhs;
        }
        else{

            start = rhs;
            end = *this;
        }

        int run = end.x - start.x;
        int rise = end.y - start.y;

        double m = ((double) rise) / ((double) run);

        double b = start.y - (m * start.y);

        for(int i = start.x; i < end.x; ++i){

            double y = (m * i) + b;

            int rounded = (y > 0.0) ? floor(y + .50) : ceil(y - 0.5);

            points.push_back(Unit(i, i));
            cout<<"Expected Output : "<< points[points.size()-1].x << " " << points[points.size()-1].y <<endl;
        }

        cout << endl;

        for (auto&p : points){

            cout<<"Actual Output : "<< p.x << " " << p.y << endl;
        }

        return points;

    }
};


int main()
{
    Unit a, b(10,10);

    auto c = a.getPoints(b);

    cout <<endl;

    for(auto& d: c){

        cout<<"Recieved Output : "<< d.x << " " << d.y << endl;
    }

    return 0;
}

ВЫХОД

Expected Output : 0 0
Expected Output : 1 1
Expected Output : 2 2
Expected Output : 3 3
Expected Output : 4 4
Expected Output : 5 5
Expected Output : 6 6
Expected Output : 7 7
Expected Output : 8 8
Expected Output : 9 9

Actual Output : 9 9
Actual Output : 9 9
Actual Output : 9 9
Actual Output : 9 9
Actual Output : 9 9
Actual Output : 9 9
Actual Output : 9 9
Actual Output : 9 9
Actual Output : 9 9
Actual Output : 9 9

Recieved Output : 2.07386e-317 6.9151e-310
Recieved Output : 6.9151e-310 6.95256e-310
Recieved Output : 6.9151e-310 6.95256e-310
Recieved Output : 6.9151e-310 6.95256e-310
Recieved Output : 6.9151e-310 6.95256e-310
Recieved Output : 6.9151e-310 6.95256e-310
Recieved Output : 6.9151e-310 6.95256e-310
Recieved Output : 6.9151e-310 6.95256e-310
Recieved Output : 6.9151e-310 6.95256e-310
Recieved Output : 6.9151e-310 6.95256e-310

1 Ответ

0 голосов
/ 26 ноября 2018

В вашем классе есть ссылочные переменные.

Когда вы создаете копию класса через конструктор копирования по умолчанию, ссылочные переменные нового объекта будут ссылаться на такие же объекты, которыессылки на источник упоминаются.Которые в этом случае будут переменными-членами исходного объекта.

Вы, вероятно, намеревались, чтобы ссылки каждой Unit ссылались на члены того же Unit.Для этого вам нужно написать свой собственный конструктор копирования, который соответствующим образом инициализирует ссылки.(И вы должны написать Move-конструктор тоже).

NB.Лучшим подходом было бы вообще не использовать ссылочные переменные.Вместо этого вы можете использовать функцию-член double& x() { return n[0]; }.

...