Які є випадки використання та переваги покажчиків? [зачинено]


10

Я часто намагаюся бачити переваги покажчиків (крім програмування на низькому рівні).

Навіщо використовувати char * замість String або char [] або які переваги приносить арифметика вказівника.

То які плюси та випадки використання покажчиків?


6
Це буде звучати трохи елітарно, але якщо ви повинні запитати про плюси і мінуси покажчиків, вам, швидше за все, вони не потрібні.
Яс

3
Мабуть! Але питання все-таки актуальне!
Золомон

1
Це також насправді не є мовно-агностичним, оскільки не всі, що багато мов програмування мають реальні покажчики в сенсі С.
Девід Торнлі

Відповіді:


6

Покажчики необхідні для динамічного розташування пам’яті, багатьох структур даних та ефективної обробки великої кількості даних. Без покажчиків вам доведеться розподіляти всі програмні дані в усьому світі або за функціями або еквівалентом, і ви б не зверталися, якби кількість даних зростала понад те, що ви спочатку дозволяли. Я не вагаюся використовувати тут абсолюти, але, наскільки я знаю, усі сучасні комп'ютерні мови мають вказівники в тій чи іншій формі.

У більшості мов, які використовують покажчики, є певні види посилань, які є покажчиками, і, можливо, певні види посилань, яких немає, і немає додаткової примітної різниці. consОсередок Ліспа - це пара покажчиків, хоча а fixnum- не вказівник. У Java змінна, яка використовується для екземпляра класу, - це вказівник, але intце не так. Синтаксис мови не відображає цього.

C незвично тим, що покажчики є необов'язковими, явними та дозволяють явну арифметику вказівника. Це абсолютно можливо записати struct foo bar; struct foo * baz;, і як тільки ви виділили пам'ять, bazви можете використовувати як barі bazпредставити struct foos. Оскільки вказівники необов’язкові, корисно мати нотаційні відмінності. (Це важливо в C ++ для розумних покажчиків, оскільки це дано boost::shared_ptr<foo> bar;, bar.reset()має одне значення і bar->reset(), ймовірно, має набагато інше.)

(Насправді явні покажчики часто використовувались в інших мовах, коли C спочатку розроблявся, як, наприклад, ^у Pascal. C - це більш давня мова, ніж більшість із поширених сьогодні, і це показує.)

Однією з цілей дизайну C було написати запис в Unix, і тому йому потрібно було детально обробляти місця пам'яті. (C насправді є однією з сімей мов впровадження системи, поширених під час його проектування. Іншим прикладом є Cybol для комп'ютерів з керуючими даними. C - той, що став великим хітом.) Отже, можна безпосередньо маніпулювати C покажчиками, призначення адрес пам'яті та обчислення нових. Це також призвело до деяких дизайнерських рішень в масивах C. C ґрунтується в значній мірі на арифметиці вказівника, і дійсно масив перетворюється на покажчик у дуже багатьох ситуаціях. Передача змінних функціям C за посиланням здійснюється покажчиком. Не було гострої потреби в масивах та передачі змінних за посиланням у тому вигляді, який мали інші сучасні мови, тому C не отримав їх.

Отже, відповідь полягає в тому, що в більшості мов нині ви постійно використовуєте покажчики, не нагадуючи про це. У мові C, і меншою мірою C ++, ви використовуєте вказівники або для того, щоб робити речі низького рівня, або виконувати речі вищого рівня, для яких немає спеціальних позначень.


дуже приємна відповідь
Кейт Григорій

1
Я приймаю цю відповідь, оскільки вона найкраще описує різницю, яку я не міг зрозуміти між покажчиками в C / C ++ та Посиланням на Java.
ОліверС

Було б добре додати коротке пояснення того, чому Java не використовує покажчики, щоб краще уточнити сприйнятий "Гослінг" Гослінг (головний творець Java).
Гвідо Ансельмі

10

Складні структури даних. Ви не можете створити щось на зразок пов’язаного списку чи двійкового дерева без покажчиків.

Немає "плюсів" і "мінусів" покажчиків. Вони просто інструмент, як молоток.


5
У Java немає покажчиків. Тим не менш, можна створити пов'язаний список і двійкове дерево. Існує різниця між посиланнями (як у Java) та вказівниками (як у C).
StartClass0830

7
Немає різниці між посиланнями та покажчиками. Арифметика вказівника є специфічною для С; Є й інші мови, які мають покажчики, але не мають арифметики вказівника (наприклад, Pascal).
zvrba

1
Покажчики та посилання не синонімічні, як ви думаєте. Прочитайте це, щоб побачити відмінності. stackoverflow.com/questions/57483 / ...
StartClass0830

4
Для вирішення перших двох елементів цього списку: посилання на ЯВЛЕННЯ МОЖУТЬ бути перепризначені, і вони МОЖУТЬ вказувати на нуль. Відмітна особливість вказівника полягає в тому, що дозволяє побічно посилатися на інший об’єкт. Мій тест лакмусу: якщо ви можете побудувати кругову структуру даних (яку ви можете використовувати з посиланнями на Java), це вказівник. (Зверніть увагу, що ви не можете побудувати кругову структуру даних із посиланнями на C ++.)
zvrba

1
Існує різниця між вказівниками та посиланнями. Наприклад, у C # є і те , і інше . ( blogs.msdn.com/b/ericlippert/archive/2009/02/17/… )
Стівен Еверс

2
  • За допомогою покажчиків ви можете виділяти та розбирати пам'ять під час виконання.
  • І ви можете використовувати великі структури даних за межами дозволеного обсягу без копіювання.

Посилання на C ++, Java та інших мовах такого ж типу - лише "безпечні покажчики". І ці посилання багато використовуються на Java.


1
Посилання на C ++ НЕ є безпечними покажчиками. Посилання на C ++ взагалі не мають нічого спільного з покажчиками. Посилання на C ++ - псевдоніми . Їх не можна призначати NULL, і вони не можуть бути змінені після їх створення.
Біллі ONeal

@Billy: Посилання на C ++ зазвичай реалізуються за допомогою покажчиків і працюють подібним чином у деяких речах, тому люди продовжують думати про них як про якийсь обмежений покажчик.
Девід Торнлі

2

Практично будь-якій комп'ютерній програмі потрібно перевіряти та змінювати значення в пам'яті (відомі як зазирвання та ковзання, для тих із нас, хто досить старий). Вам потрібно контролювати, де в пам'яті знаходяться ці значення, щоб результат був передбачуваним (а в деяких випадках важливий порядок: завантаження виконуваного коду є одним із прикладів). Тому потрібно мати тип даних, який представляє місце в пам'яті. Навіть якщо ваше програмне середовище ховає це під абстракцією, воно все одно є.


2

char*є крихким прикладом покажчиків. Вам, мабуть, краще використовувати std::string(або якийсь кращий тип, який обробляє вашу унікальність / ансі / багатобайтову особливість), ніж char*. Майже для будь-якого іншого прикладу покажчиків ( Employee*, PurchaseOrder*, ...), однак, є багато переваг:

  • Обсяг, більший, ніж одна функція - виділіть об’єкт на купі і перенесіть вказівник довгий час
  • швидша функція вимагає великих об’єктів, оскільки у вас немає вартості копіювання прохідної вартості
  • один із способів включити функцію змінити передані їй параметри
  • заощаджують простір та час у колекціях, копіюючи лише адресу, а не цілий об’єкт

Насправді вказівники настільки важливі, що більшість мов, схоже, не мають їх, насправді мають лише вони. Довідкові типи в C # і Java по суті є вказівниками, замаскованими як тверді об'єкти.

Тепер маніпуляція вказівником ( p++на вказівнику чи p += delta) - ціла історія. Деякі люди думають, що це небезпечно, деякі вважають, що це здорово. Але це ще далі від вашого питання.


1

Покажчики можуть бути швидшими і можуть мати менші накладні витрати, як у структурі даних, так і при зменшенні сліду виконання програми. (Будь ласка, зверніть увагу на слово "можна".)

Загалом, правило полягає в тому, що якщо ви виділили ресурс, або виконуючи власний розподіл, або змусивши щось зробити це від вашого імені, ваша робота - звільнити його, коли буде зроблено.

Тягар виконання вищезазначеного полягає в тому, щоб повернути відповідальність розробнику, а не вимагати виконання часу. Це має ще деякі переваги в тому, що речі можна довше жити, або перетинати кордони, або утилізувати у більш підходящий час, або не потрібно переносити вагу сміттєзбірника навколо.

У екзотичних випадках, що зазвичай включають винятки та сферу застосування, є деякі крайні випадки, які вимагають бути трохи обережнішими, якщо код уникає очищення. Реально ці випадки можна розробити навколо. Ми прожили без керованого коду багато десятиліть.

Часто те, що робить покажчики «важкими» - це просто не розуміння того, що відбувається на апаратному рівні. Це не що інше, як непряме.

Покажчики дають вам набагато більше необробленого доступу, і це може бути дуже корисною, розумною чи необхідною. Ви можете вказувати куди завгодно і ставитися до цього майже як до всього. Якщо ви використовуєте свої богоподібні сили для добра, це дуже, дуже добре.

Зворотна сторона, як правило, марнує, забувши випустити щось, або випустити його не раз, або посилатися на щось після його звільнення, або перешкоджаючи чомусь, коли ви нікуди не вказуєте. Ці речі часто призводять до вражаючих збоїв, і якщо чесно сказати, зазвичай це свідчить про те, що у вас є логічна проблема, а не покажчики крихкі.

Якщо ви надійний розробник, використання покажчиків не має бути більш проблематичним, ніж будь-яка інша структура даних. Знову ж таки, це не ракетна наука, і люди робили це десятиліттями, навіть не моргнувши оком. Цього дня просто навчають менше.

Все, що було сказано, якщо у вас немає необхідності в покажчиках, випадковість та екзотичні випадки, які забезпечує хороший збір сміття, робить роботу в керованих умовах набагато приємнішою. Чудово вміти схопити якусь пам’ять, використовувати її та відмовитися від неї, знаючи, що через деякий час вона може бути відкинута, якщо це має сенс зробити. Це трохи менше коду з боку кодера, в обмін на час виконання, який робить додатковий підйом.


0

Найкраща відповідь насправді включена у запитання: покажчики призначені для програмування низького рівня. Звичайно, якщо ви використовуєте C, не використовуйте покажчики - це як програмування однією рукою, зав'язаною за спиною, але відповідь на це - використовувати мову вищого рівня.


-1

Покажчики забезпечують видимість машини, необхідну для найцікавішого програмування. Більшість сучасних мов просто приховують від вас стиглі шматочки.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.