Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.67/9: Рейтинг темы: голосов - 9, средняя оценка - 4.67
 Аватар для Fatmarmelad
34 / 10 / 2
Регистрация: 20.02.2016
Сообщений: 1,613

Почему Лафоре использует указатели на указатели, вместо обмена значениями указателей?

17.10.2018, 20:59. Показов 1944. Ответов 25
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Доброго времени суток!
Задался теоретическим вопросом. Читал пример из книги Лафоре ОБЪЕКТНО-ОРИЕНТИРОВАННОЕ
ПРОГРАММИРОВАНИЕ В C++, код persort.cpp// сортировка объектов через массив указателей на них. Рассматривается массив указателей на объекты. Автор пишет, что быстрее рассортировать в массиве сами указатели через указатели на них, потому что
"Таким образом мы исключаем необходимость перемещения объектов в памяти, которое отнимает много времени, если объекты очень большие" . То есть идёт работа с указателями на указатели. Я не понимаю, почему нельзя просто менять
значения адресов, которые хранятся в указателях, одно значение записывать в один указатель, а его первоначальное
значение- в другой. Ключевым ведь является то, что если я поменяю в указателе значение - адрес объекта, это же не значит
что тот объект, на который данный указатель указывал, переместиться на этот этот новый адрес
(как процитировано выше), правильно ? Или я чего-то не понимаю? Код из книги ниже, но зачем же усложнять указателями на указатели?


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
55
56
57
58
59
60
61
62
63
64
65
#include <iostream>
#include <string>                 //for string class
using namespace std;             
 
class person                      //class of persons
   {
   protected:
      string name;                //person's name
   public:
      void setName()              //set the name
         { cout << "Enter name: "; cin >> name; }
      void printName()            //display the name
         { cout << endl << name; }
      string getName()            //return the name
         { return name; }
   };
 
int main()
   {
   void bsort(person**, int);     //prototype
   person* persPtr[100];          //array of pointers to persons
   int n = 0;                     //number of persons in array
   char choice;                   //input char
          
   do {                           //put persons in array
      persPtr[n] = new person;    //make new object
      persPtr[n]->setName();      //set person's name
      n++;                        //count new person
      cout << "Enter another (y/n)? "; //enter another
      cin >> choice;              //   person?
      }
   while( choice=='y' );          //quit on 'n'
 
   cout << "\nUnsorted list:";
   for(int j=0; j<n; j++)         //print unsorted list
      { persPtr[j]->printName(); }     
 
   bsort(persPtr, n);             //sort pointers
 
   cout << "\nSorted list:";
   for(j=0; j<n; j++)             //print sorted list
      { persPtr[j]->printName(); }
   cout << endl;
   return 0;
   }  //end main()
 
void bsort(person** pp, int n)    //sort pointers to persons
   {                              
   void order(person**, person**);  //prototype
   int j, k;                      //indexes to array
 
   for(j=0; j<n-1; j++)           //outer loop
      for(k=j+1; k<n; k++)        //inner loop starts at outer
          order(pp+j, pp+k);       //order the pointer contents
   }
 
void order(person** pp1, person** pp2)  //orders two pointers
   {                              //if 1st larger than 2nd,
   if( (*pp1)->getName() > (*pp2)->getName() )
      {
      person* tempptr = *pp1;     //swap the pointers
      *pp1 = *pp2;
      *pp2 = tempptr;
      }
   }
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
17.10.2018, 20:59
Ответы с готовыми решениями:

Массивы указателей и указатели на указатели
В чем разница между массивами указателей и указателями на указатели? Может, между ними такая же разница, как между массивами и...

Указатели на указатели с числами. Почему можно присвоить число в 4-ый элемент, если массив из 2 элементов?
Есть массив int **mas; mas=new int*; // выделил место под пять строк, верно ? mas=new int;// выделил для первой строки матрицы два...

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

25
0 / 1 / 0
Регистрация: 12.10.2018
Сообщений: 10
17.10.2018, 21:38
Попробую объяснить, хотя я не опытный. Вы хотите заменить тип person ** на person*.
Тут надо хорошо понимать указатели. Проблема в том, что в функцию указатели передаются по значению(её копии). То есть, если вы сделаете вот так:
C++
1
2
3
4
5
6
void order(person* p1, person* p2)  //orders two pointers
{                              //if 1st larger than 2nd,
person * tmp=p1;
p1=p2;
p2=tmp;
}
Вы на самом деле измените не значения ОРИГИНАЛЬНЫХ указателей, а его копий. Передавая же тип (person **) - вы получаете доступ к значению оригинального указателя с помощью оператора разыменования(*):
C++
1
2
3
4
5
6
void order(person** p1, person** p2)  //orders two pointers
{                              //if 1st larger than 2nd,
person ** tmp=*p1;
*p1=*p2;
*p2=*tmp;
}
0
 Аватар для Fatmarmelad
34 / 10 / 2
Регистрация: 20.02.2016
Сообщений: 1,613
17.10.2018, 21:44  [ТС]
alexbez, то есть смысл в том, чтобы во время сортировки задействовать меньше памяти, не создавая копии?
А если всё же , даже если, использовать копии, как в первом коде, объекты будут перемещаться в памяти, как пишет Лафоре? я так понимаю, что нет.
0
0 / 1 / 0
Регистрация: 12.10.2018
Сообщений: 10
17.10.2018, 21:57
Fatmarmelad, возможно я поторопился с ответом. Увидел дату вашей регистрации, после того как написал ответ. Я думал это вопрос от новичка. Наверно я что-то не то написал. Извините.
0
 Аватар для Fatmarmelad
34 / 10 / 2
Регистрация: 20.02.2016
Сообщений: 1,613
17.10.2018, 23:24  [ТС]
alexbez, я и есть новичок. С++ учу в свободное время. Поэтому и спрашиваю. Меня заинтересовало, почему Лафоре пишет про перемещение объектов в памяти.
0
 Аватар для Nishen
1357 / 856 / 365
Регистрация: 26.02.2015
Сообщений: 3,814
17.10.2018, 23:27
Fatmarmelad, ну, так а ты попробовал запустить программу без указателей на указатели?

Добавлено через 33 секунды

Не по теме:

Цитата Сообщение от alexbez Посмотреть сообщение
Fatmarmelad, возможно я поторопился с ответом. Увидел дату вашей регистрации, после того как написал ответ. Я думал это вопрос от новичка. Наверно я что-то не то написал. Извините.
Ты что, мямля?

0
1394 / 1023 / 325
Регистрация: 28.07.2012
Сообщений: 2,813
17.10.2018, 23:40
Fatmarmelad, все довольно просто. В случае обычной сортировки имеется массив элементов типа T=person. Указатель на элемент этого массива будет иметь тип T *=person *.
В твоем же случае у тебя массив элементов типа T=person *. Тогда указатель на элемент этого массива будет иметь тип T *=person **. Вот отсюда и берется двойной указатель.

Вся суть подхода в том, чтобы избежать дорогостоящего копирования элементов массива. Обмен местами двух элементов типа T=person может занимать на порядок больше времени, чем обмен двух элементов типа T=person *.
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
18.10.2018, 01:43
alexbez, вы верно в целом все описали.

Цитата Сообщение от Fatmarmelad Посмотреть сообщение
Код из книги ниже, но зачем же усложнять указателями на указатели?
В данном случае это не усложнение, а обоснованное действие. Вы не сможете поменять местами содержимое двух указателей без этой дополнительной косвенности.

Возьмите и замените тип указателя на обычный int.
C++
1
2
3
4
5
6
void swap(int * a, int * b)
{
    int tmp = *a;
    *a = *b;
    *b = tmp;
}
А теперь нам надо поменять местами значение двух указателей на int, вместо двух int`ов. Получаем:
C++
1
2
3
4
5
6
void swap(int ** a, int ** b)
{
    int * tmp = *a;
    *a = *b;
    *b = tmp;
}
Добавлено через 5 минут
Fatmarmelad, Единственное, что здесь нужно знать про указатели, что int * - это такой тип.

Вы, если не понимаете как это так, пишите функцию с условным T (как вам выше объяснили), а потом меняйте T на тот тип, который нужен. Вот общая функция обмена местами значений двух переменных:
C++
1
2
3
4
5
6
void swap(T * a, T * b)
{
   T tmp = *a;
   *a = *b;
   *b = tmp;
}
Если вы вместо T подставите int (т.е. таким образом нас интересует обмен значений двух переменных типа int), то получите первую функцию из моего примера.
Если подставите вместо T тип int * (т.е. таким образом нас интересует обмен значений двух переменных типа указатель на int), то получите функцию из второго примера, и примерно тоже самое, что было дано в книге.
0
Just Do It!
 Аватар для XLAT
4189 / 2644 / 654
Регистрация: 23.09.2014
Сообщений: 8,917
Записей в блоге: 3
18.10.2018, 08:34
Цитата Сообщение от Fatmarmelad Посмотреть сообщение
Меня заинтересовало, почему Лафоре пишет про перемещение объектов в памяти.
Лафоре предлагает сортировать не массив объектов, а массив указателей на эти объекты.
Почему?
Представьте что у вас есть фильмотека из 1000 фильмов и вы решили упорядочить их по году выхода.
Вы предпочтете физически разложить их в своем каталоге по выбранному критерию или все же предпочтете составить таблицу указателей на эти файлы?
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
18.10.2018, 12:48
Цитата Сообщение от XLAT Посмотреть сообщение
Вы предпочтете физически разложить их в своем каталоге по выбранному критерию или все же предпочтете составить таблицу указателей на эти файлы?
я предпочту std::map, Бро.
0
Заблокирован
18.10.2018, 14:40
Цитата Сообщение от hoggy Посмотреть сообщение
я предпочту std::map
он же медленный
0
 Аватар для Fatmarmelad
34 / 10 / 2
Регистрация: 20.02.2016
Сообщений: 1,613
18.10.2018, 21:23  [ТС]
Я задался этой темой из-за слов, которые привёл выше
"Таким образом мы исключаем необходимость перемещения объектов в памяти, которое отнимает много времени, если объекты очень большие" .
Сейчас я понимаю, что массив объектов в функции это Class*, а массив указателей на них Class**. Иначе записать нельзя.
C++
1
void func(Class**, int);
Добавлено через 24 минуты
Вдогонку. Насколько я сейчас понимаю, невозможно поменять значения адресов элементов массива, потому что они -константы. Прав ли я? То есть код ниже невозможен.

C++
1
2
3
temp = &arr[1];
&arr[1]=&arr[2];
&arr[2]=temp;
0
Just Do It!
 Аватар для XLAT
4189 / 2644 / 654
Регистрация: 23.09.2014
Сообщений: 8,917
Записей в блоге: 3
19.10.2018, 01:06
Цитата Сообщение от Fatmarmelad Посмотреть сообщение
void func(Class**, int);
можно так:
C++
1
void func(Class* m[], int);
Цитата Сообщение от Fatmarmelad Посмотреть сообщение
То есть код ниже невозможен.
да, невозможен.
Представь ячейку памяти в своем компе, которая что-то хранит.
У неё есть номер. Он же и адрес.
0
Неэпический
 Аватар для Croessmah
18144 / 10728 / 2066
Регистрация: 27.09.2012
Сообщений: 27,026
Записей в блоге: 1
19.10.2018, 10:21
можно так
И в чем разница?
0
 Аватар для COKPOWEHEU
4079 / 2677 / 432
Регистрация: 09.09.2017
Сообщений: 11,888
19.10.2018, 10:47
В том, что передается массив указателей, а не указатель на указатель. Такая запись может служить подсказкой программисту.
1
Неэпический
 Аватар для Croessmah
18144 / 10728 / 2066
Регистрация: 27.09.2012
Сообщений: 27,026
Записей в блоге: 1
19.10.2018, 10:52
COKPOWEHEU, передается в обоих случаях указатель на указатель и первая запись лучше отражает тип переменной.
0
 Аватар для COKPOWEHEU
4079 / 2677 / 432
Регистрация: 09.09.2017
Сообщений: 11,888
19.10.2018, 11:11
Croessmah, хорошо, давайте я повторю ключевую фразу:
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Такая запись может служить подсказкой программисту.
Разумеется, с точки зрения языка эти записи эквивалентны. Но вы же не будете писать код в одну строчку только потому что компилятору все равно?
0
"C with Classes"
2022 / 1404 / 523
Регистрация: 16.08.2014
Сообщений: 5,885
Записей в блоге: 1
19.10.2018, 11:18
Цитата Сообщение от Croessmah Посмотреть сообщение
указатель на указатель
нет такого типа данных!
0
Неэпический
 Аватар для Croessmah
18144 / 10728 / 2066
Регистрация: 27.09.2012
Сообщений: 27,026
Записей в блоге: 1
19.10.2018, 11:20
COKPOWEHEU,
Во-первых, такая запись сама по себе воспринимается сложнее.
Во-вторых, такая запись всё равно не дает никаких гарантий.
В-третьих, слабо верится, что разработчику функции нужна эта подсказка, а для пользователя она всё равно недостаточна, нужно лезть в документацию.
В-четвертых, удобство такой подсказки - это как выбор цвета шапки, кому-то нравится, кому-то нет. Лично я из второй категории и считаю такую запись говеной.

Добавлено через 17 секунд
_stanislav, молодец
0
Just Do It!
 Аватар для XLAT
4189 / 2644 / 654
Регистрация: 23.09.2014
Сообщений: 8,917
Записей в блоге: 3
19.10.2018, 11:23
Цитата Сообщение от Croessmah Посмотреть сообщение
И в чем разница?
если вам нужна разница, то можно и так:
C++
1
void func(Class*& m[], int)
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
19.10.2018, 11:23
Помогаю со студенческими работами здесь

Указатели и указатели на указатели, а также типы данных
Недавно начал изучать Си, перешел с Delphi. Много непонятного и пока процесс идет медленно. Накачал литературы, буду изучать) Щас...

Указатели. Важность указателей
Здарова! Я хорошо понимаю (относительно хорошо, конечно), что такое указатели. Я слышал, что такие языки как Java и C# не имеют в...

Указатели. Вычитание указателей
Сам читаю книгу Шилдта. Глава с указателями, написано - &quot;Если складывать указатели нельзя, то разрешается вычитать один указатель из...

Инициализация массива указателей на указатели
Всем привет. Есть такой код: char **pchAr = new char*; //в цикле по i pchAr = new char; Как заменить эту строку,...

Указатели. Сравнение двух указателей и их sizeof()
Есть код: int main() { int x = 10; int y = 10; int *xptr = &amp;x; int *yptr = &amp;y; setlocale(LC_ALL, &quot;Russian&quot;); //сравниваем...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru