Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.80/5: Рейтинг темы: голосов - 5, средняя оценка - 4.80
0 / 0 / 0
Регистрация: 14.07.2016
Сообщений: 1
1

Не меняются значения элементов вектора через указатели

27.08.2019, 22:14. Показов 964. Ответов 11
Метки нет (Все метки)

Вот учусь программировать. Дошел до всяких там указателей.

Программа выводит два числа:
-858993460
2
Переменная меняется почему-то только у последнего элемента вектора. Как это исправить?

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
#include <iostream>
#include <vector>
 
namespace gui{
    struct Window{
        int id;
        std::string title;
    };
    std::vector <Window> Windows;
    Window *createWindow(){
        Windows.resize(Windows.size() + 1);
        return &Windows[Windows.size() - 1];
    }
};
int main(int argc, char *argv[]){   
    gui::Window *per = gui::createWindow();
    gui::Window *per2 = gui::createWindow();
 
    per->id = 1;
    per2->id = 2;
 
    for(int a = 0; a < gui::Windows.size(); a++){
        std::cout << gui::Windows[a].id << std::endl;
    }
 
    system("pause");
    return EXIT_SUCCESS;
}
0

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

Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
27.08.2019, 22:14
Ответы с готовыми решениями:

Создание вектора wstring через указатели
Вот так правильно? Обратите особое внимание на цикл do-while. vector&lt;wstring&gt; MachinesList; ...

Сформировать вектора х(4), значения элементов которого являются максимальные значения столбцов матрицы
составить программу формирования вектора х(4), значения элементов которого являются максимальные...

Функция меняющая местами два значения через указатели
Функция должна поменять местами значения через указатели. Программа запускается, но не работает...

Вычислить количество элементов, больших среднего значения элементов вектора
Вычислить количество элементов, больших среднего значения элементов вектора

11
Комп_Оратор)
Эксперт по математике/физике
8719 / 4428 / 598
Регистрация: 04.12.2011
Сообщений: 13,270
Записей в блоге: 16
27.08.2019, 22:29 2
Цитата Сообщение от roninblade11 Посмотреть сообщение
Переменная меняется почему-то только у последнего элемента вектора.
roninblade11, вы создали вектор размером, равным размеру элемента. Это все равно что создать вольер для слонов и поставить туда столько клеток, сколько сантиметров укладывается в длину одного слона. Потом в последнюю вы посадили слона. У всех предыдущих elephant.size()-1 штук сидят неинициализированные слоны (слоны чехлы). У них нет данных. Попытка распечать даст мусор или пусто (у int и string - разная реакция на отсутствие инициализации). Победить это можно целенаправленной деятельностью. Хотя и случайно, тоже может получиться.
Совет: почитайте описание класса vector и особенно внимательно, - конструкторы. Можете создать из массива, можно агрегатно инициализировать, а можно запушить по мере поступления. Почитайте, там не сложно.
0
Модератор
Эксперт С++
11071 / 9128 / 5485
Регистрация: 18.12.2011
Сообщений: 24,399
28.08.2019, 11:10 3
Настоятельно не рекомендую так делать.
Для контейнеров есть стандартные действия для помещения объекта в контейнер и его вывода
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
#include <iostream>
#include <vector>
#include <string>
 
namespace gui 
{
    struct Window {
        int id;
        std::string title;
    };
};
int main() {
    std::vector <gui::Window> Windows;
    gui::Window t;
    t.id = 1;
    Windows.push_back(t);
    t.id = 2;
    Windows.push_back(t);
    for (auto px = Windows.begin(); px != Windows.end();++px) {
        std::cout <<px->id << std::endl;
    }
// Или так:
    for (auto x:Windows) {
        std::cout <<x.id << std::endl;
    }
 
    system("pause");
    return EXIT_SUCCESS;
}
0
183 / 181 / 66
Регистрация: 15.02.2015
Сообщений: 515
28.08.2019, 11:25 4
Рекомендации это конечно хорошо, но ошибка у ТС в том, что resize делает невалидными все полученные ранее итераторы и адреса элементов этого вектора.
C++
1
2
3
4
...
    gui::Window *per = gui::createWindow();   // взяли адрес
    gui::Window *per2 = gui::createWindow(); // выполнили resize и адрес первого элемента (как и всех остальных) поменялся
...
2
Комп_Оратор)
Эксперт по математике/физике
8719 / 4428 / 598
Регистрация: 04.12.2011
Сообщений: 13,270
Записей в блоге: 16
28.08.2019, 13:12 5
Цитата Сообщение от Operok Посмотреть сообщение
ошибка у ТС в том, что resize делает невалидными все полученные ранее итераторы
Я не заметил полученных ранее итераторов. В функции createWindow() на пустом глобальном (!!) векторе делается resize(). Захватывающий захват или замыкание (в мозгу). То есть, нужно функции повторить. И да, - оба указателя указывают на один и тот же вектор. Последний ресайз действует)
0
15110 / 8110 / 1958
Регистрация: 30.01.2014
Сообщений: 13,782
28.08.2019, 13:58 6
Цитата Сообщение от IGPIGP Посмотреть сообщение
Я не заметил полученных ранее итераторов.
Зато есть полученные указатели.
Operok абсолютно верно все написал.
0
Комп_Оратор)
Эксперт по математике/физике
8719 / 4428 / 598
Регистрация: 04.12.2011
Сообщений: 13,270
Записей в блоге: 16
28.08.2019, 15:54 7
Цитата Сообщение от DrOffset Посмотреть сообщение
Operok абсолютно верно все написал.
Я не говорил, что Operok, написал неправильно. Это вообще не мой стиль. Я говорил что
Цитата Сообщение от IGPIGP Посмотреть сообщение
Я не заметил полученных ранее итераторов.
и что стиль работы с функциями наводит на мысль о том, что векторы в частности и stl вообще, это ещё не нужно. Это к тому, что ресайз по размеру элемента говорит о том же.
0
15110 / 8110 / 1958
Регистрация: 30.01.2014
Сообщений: 13,782
28.08.2019, 15:58 8
Цитата Сообщение от IGPIGP Посмотреть сообщение
тот же вектор с тем же ресайзом
Справедливости ради, ресайз там разный, на +1 от предыдущего.
1
Комп_Оратор)
Эксперт по математике/физике
8719 / 4428 / 598
Регистрация: 04.12.2011
Сообщений: 13,270
Записей в блоге: 16
28.08.2019, 16:33 9
Цитата Сообщение от DrOffset Посмотреть сообщение
Справедливости ради, ресайз там разный, на +1 от предыдущего.
Да, верно. Имена типа элементов и вектора перепутал. На одну букву отличаются. Конечно, пользоваться старыми адресами после resaize() нельзя. Согласен. Ими вообще лучше не пользоваться.
0
672 / 288 / 99
Регистрация: 04.07.2014
Сообщений: 810
28.08.2019, 17:15 10
Задача std::vector - это управление памятью для хранения данных. Он сам решает сколько выделить память, когда освободить память, когда пересоздать массив элементов.

Разбор по шагам:

Изначально есть пустой массив. (для простоты предполагаю что в vector есть поле data которое смотрит на выделенную память)

Название: bad_vector_using-0.png
Просмотров: 44

Размер: 6.3 Кб

После Windows.resize(Windows.size() + 1); будет выделена пять и вектор будет смотреть на неё. 0-й элемент инициализируется по умолчанию.

Название: bad_vector_using-1.png
Просмотров: 43

Размер: 7.4 Кб

После per = сохраниться текущая ссылка на 1-й элемент массива

Название: bad_vector_using-2.png
Просмотров: 43

Размер: 10.6 Кб

После Windows.resize(Windows.size() + 1); потребовалось больше памяти, поэтому std::vector выделил новую память, скопирует (переместит) значения, новый элемент инициализирует значением по умолчанию. и освободит предыдущий участок памяти, но per продолжает смотреть на невалидный участок памяти!!!!

Название: bad_vector_using-3.png
Просмотров: 44

Размер: 16.2 Кб

После per2 = сохраняется текущая ссылка на 2-й элемент массива

Название: bad_vector_using-4.png
Просмотров: 45

Размер: 19.5 Кб

После per->id=1 per2->id=2 будет запись в ту память, на которую смотрят эти указатели.
Название: bad_vector_using-5.png
Просмотров: 44

Размер: 19.1 Кб
1
Комп_Оратор)
Эксперт по математике/физике
8719 / 4428 / 598
Регистрация: 04.12.2011
Сообщений: 13,270
Записей в блоге: 16
28.08.2019, 19:26 11
Цитата Сообщение от AlexVRud Посмотреть сообщение
Задача std::vector - это управление памятью для хранения данных.
В данном виде это очень медленно так как может вызвать реалокейт в любой момент.
Цитата Сообщение от AlexVRud Посмотреть сообщение
но per продолжает смотреть на невалидный участок памяти!!!!
А у ТС происходит разыменование:

C++
1
2
3
4
5
gui::Window *per = gui::createWindow();
    gui::Window *per2 = gui::createWindow();//конец валидности  per
 
    per->id = 1;// этого делать уже нельзя
    per2->id = 2;
0
Комп_Оратор)
Эксперт по математике/физике
8719 / 4428 / 598
Регистрация: 04.12.2011
Сообщений: 13,270
Записей в блоге: 16
29.08.2019, 07:44 12
по началу не понял смысла поста AlexVRud. Показалось, что отстаивается правильность подхода ТС. Не было времени вчитаться. Теперь перечитал и понял. Всё верно. Последний мой пост можно удалить.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
29.08.2019, 07:44

Передача значения размера вектора через переменную
Здравствуйте! Структура вершины в дереве: struct node { int x; vector&lt;node*&gt; adj;...

При выборе значения в одном ComboBox меняются значения в других
Помогите, пожалуйста. Есть несколько ComboBox Выбирая значение в одном, почему-то...

Значения элементов вектора
Программа получает N параметров вызова (аргументы командной строки). Эти параметры – элементы...

Пересчитать значения элементов вектора М размерности n
Помогите, пожалуйста, с решением этого задания. Пересчитать значения элементов вектора М...


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.