3 / 3 / 2
Регистрация: 19.02.2014
Сообщений: 142
1

Некоректное использование указателей

15.10.2017, 13:12. Показов 913. Ответов 5
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
День добрый! У меня есть класс Burnes_Hut, который содержит в себе не который массив (dCells3D) и деревовидный граф (dGraphTree), который задаётся рёбрами с двумя указателями - *Parent и *Child. Задача состоит в том, чтобы при создании новой ячейки (dCells3D) создавалось ребро, ссылается на предыдущую ячейку и на новосозданную. Вычисления рекурсионные: создаётся одна корневая ячейка (void dBarnes_Hut :: CreateFirstCell()), потом делится, затем эти новые ячейки тоже делятся и т.д. (void dBarnes_Hut :: CreateCellsRecursion(const dCell3D& ParentCellP)). Для простоты процесс создания новых ячеек опустил, так как не в этом проблема. Дело в том, что при создании первой ячейки в графе появляется указатель Root, по которому к первой ячейке можно обратиться, но если добавить хотя бы один элемент массив с ячейками, указатель Root теряет размер ячейки (переменная double Size), но не теряет координаты. В чём может быть проблема?

Некоректное использование указателей


C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
//---dGraph.h---//
//------------------------------------//
template <class T>
struct dGraphEdge {
    dGraphEdge(T* ParentP, T* ChildP) {
        Parent = ParentP;
        Child = ChildP;
    }
    ~dGraphEdge() {
        Parent = nullptr;
        Child = nullptr;
    }
 
    T* Parent = nullptr;
    T* Child = nullptr;
};
 
template <class T>
class dGraphTree {
    private:
        T* Root = nullptr;
        std :: vector <dGraphEdge <T>> Edges;
    public:
        void SetRoot(T* RootP) {
            Root = RootP;
        }
        void SetChild(T* ParentVertexP, T* ChildVertexP) {
            Edges.emplace_back(dGraphEdge <T> (ParentVertexP, ChildVertexP));
        }
 
        T* GetRoot() {
            return Root;
        }
        std :: vector <T*> GetChildren(const T* VertexP) {
            std :: vector <T*> ChildrenL;
 
            for (auto EdgeI : Edges) {
                if (EdgeI.Parent == VertexP) {
                    ChildrenL.emplace_back(EdgeI.Child);
                }
            }
 
            return ChildrenL;
        }
        T* GetParent(T* VertexP) {
            for (auto EdgeI : Edges) {
                if (EdgeI.Child == VertexP) {
                    return EdgeI.Parent;
                }
            }
 
            return nullptr;
        }
};
C++
1
2
3
4
5
6
7
8
9
10
11
12
//---dCells.h---//
//------------------------------------//
class dCell3D {
    public:
        dCell3D(const dVector3D& CoordP, const double SizeP);
        ~dCell3D() = default;
 
        double Size;
        dVector3D Coord; //---Nearest point to origin---//
 
        bool InsideCell(const dVector3D PointP);
};
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//---dCells.cpp---//
//------------------------------------//
dCell3D ::dCell3D(const dVector3D& CoordP, const double SizeP) {
    Coord = CoordP;
    Size = SizeP;
}
//----------------------------------//
bool dCell3D :: InsideCell(const dVector3D PointP) {
    if (    PointP.x >= Coord.x && PointP.x <= Coord.x + Size &&
            PointP.y >= Coord.y && PointP.y <= Coord.y + Size &&
            PointP.z >= Coord.z && PointP.z <= Coord.z + Size) {
        return true;
    } else {
        return false;
    }
}
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//---dBarnes_Hut.h---//
//------------------------------------//
class dBarnes_Hut {
    private:
        std :: vector <dCell3D> Cells;
        dGraphTree <dCell3D> Graph;
        dBeam* Beam;
 
        std :: vector <double> Mass; //---Total mass of each cell---//
        std :: vector <dVector3D> CenterOfMass; //---Center of mass of each cell---//
 
        //---Grid Creation---//
        void CreateFirstCell();
        void CreateCellsRecursion(const dCell3D& ParentCellP);
        //---Grid Creation---//
    public:
        dBarnes_Hut(dBeam& BeamP);
        ~dBarnes_Hut() = default;
 
        void CreateGrid();
};
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
//---dBarnes_Hut.cpp---//
//------------------------------------//
void dBarnes_Hut :: CreateFirstCell() {
    if (Beam -> Particles.empty()) {
        std :: cout << "dBarnes_Hut: Cannot create first cell - the beam is empty!" << std :: endl;
        return;
    }
 
    if (!Cells.empty()) {
        std :: cout << "dBarnes_Hut: Cannot create first cell - the Cells array is not empty!" << std :: endl;
        return;
    }
 
    double CellSizeL = Beam -> GetBeamSize().Greatest();
 
    Cells.emplace_back(dCell3D(Beam -> GetPosition() - dVector3D(CellSizeL / 2.0, CellSizeL / 2.0, CellSizeL / 2.0), CellSizeL));
    Graph.SetRoot(&Cells[0]);
}
void dBarnes_Hut :: CreateCellsRecursion(const dCell3D& ParentCellP) {
    if (Cells.empty()) {
        std :: cout << "dBarnes_Hut: Cannot divide cells - no root cell!" << std :: endl;
        return;
    }
 
    if (Graph.GetRoot() == nullptr) {
        std :: cout << "dBarnes_Hut: Cannot divide cells - no root vertex!" << std :: endl;
        return;
    }
 
    //---Parent cell is 2x2x2 in the local basis (x, y, z)------------------------//
    //---ChildrenPosL - array with position of the children cells in such basis---//
    std :: vector <dVector3D> ChildrenPosL {dVector3D(0, 0, 0),
                                            dVector3D(1, 0, 0),
                                            dVector3D(0, 1, 0),
                                            dVector3D(0, 0, 1),
                                            dVector3D(1, 1, 0),
                                            dVector3D(1, 0, 1),
                                            dVector3D(0, 1, 1),
                                            dVector3D(1, 1, 1)};
    std :: vector <dCell3D*> ChildCells;
 
    for (const dVector3D& CellI : ChildrenPosL) {
        Cells.emplace_back(dCell3D(dVector3D(0.0, 0.0, 0.0), 1.0));
    }
}
//----------------------------------//
void dBarnes_Hut :: CreateGrid() {
    CreateFirstCell();
    CreateCellsRecursion(Cells[0]);
}
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
15.10.2017, 13:12
Ответы с готовыми решениями:

Работа с двумерными числовыми массивами. Использование указателей. Использование функций пользователя.
Помогите пожалуйста!!!!!!! Сделать три варианта: первый вариант – передача данных между...

использование указателей
Должна быть разработана программа с меню с использованием указателей: 1. Изменить порядок...

Использование указателей
Не могли бы вы показать как решить это через указатели. Решение правильное. #include &lt;iostream&gt;...

Использование указателей
Всем привет, вот изучаю помалу С++. И уже третий час немогу впарится в Указатели недаётся мне это,...

5
3 / 3 / 2
Регистрация: 19.02.2014
Сообщений: 142
15.10.2017, 13:50  [ТС] 2
UPD: Сделал проще пример, который имеет такую же ошибку: есть массив с одним элементом и указатель на элемент, затем я использую emplace_back() и добавляю новый элемент, после чего указатель начинает указывать на ноль. Я так подозреваю, что это из-за копирования массива при вызове emplace_back(). Нужно ли заново привязывать указатель, или есть иные варианты?
C++
1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
#include <vector>
 
int main() {
    std :: vector <double> Array {0.1};
    double *Pointer = &Array[0];
    Array.emplace_back(double(0.2));
 
 
    return 0;
}
0
$ su
1605 / 520 / 97
Регистрация: 18.11.2010
Сообщений: 2,807
Записей в блоге: 2
15.10.2017, 19:30 3
Цитата Сообщение от Devilox Посмотреть сообщение
Нужно ли заново привязывать указатель
Нужно
0
284 / 232 / 114
Регистрация: 07.09.2016
Сообщений: 584
16.10.2017, 00:22 4
Лучший ответ Сообщение было отмечено Devilox как решение

Решение

у std::vector итераторы и указатели становятся невалидными после перераспределения внутреннего массива.
у std::list итераторы и указатели валидные после вставок.
у std::deque - после вставок в конец\начало указатели живие, про итераторы не помню. а так же не знаю, прописано
ли эта валидность\невалидность в стандарте. поэтому поэтому про deque мог и наврать.
1
3 / 3 / 2
Регистрация: 19.02.2014
Сообщений: 142
16.10.2017, 00:27  [ТС] 5
Понял, спасибо! Поменяю вектор на лист.
0
Любитель чаепитий
3742 / 1798 / 566
Регистрация: 24.08.2014
Сообщений: 6,016
Записей в блоге: 1
16.10.2017, 06:36 6
del
0
16.10.2017, 06:36
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
16.10.2017, 06:36
Помогаю со студенческими работами здесь

Использование указателей
я не могу понять как работает эта задача: long A={ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,...

использование указателей
Подскажите, пожалуйста, в чем здесь ошибка? #include &lt;iostream&gt; using namespace std; int x =...

использование указателей
не знал как тему даже назвать :-class CTest { public: int x; void xpp() { x++; } };

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

Использование ссылок и указателей
Добрый вечер Помогите разобраться и понять «Использование ссылок и указателей» Прочел много...

Использование указателей на функции
Составить одну из двух задач с использованием указателя на функцию 1. Составить функцию...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
6
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru