Ці ёсць карысць для unique_ptr з масівам?

std::unique_ptr has support for arrays, for instance:

std::unique_ptr p(new int[10]);

але ён патрэбны? верагодна, зручней выкарыстоўваць станд :: вектар або станд :: масіў .

Ці лічыце вы якія-небудзь выкарыстоўваць для гэтай канструкцыі?

179
Для паўнаты карціны, варта адзначыць, што няма станд :: shared_ptr , але не павінна быць, і, верагодна, будзе ў C ++ 14, калі хто-то можа быць знайшоў час пісаць прапанову. У той жа час, заўсёды ёсць падштурхоўвання :: shared_array .
дададзена аўтар Pseudonym, крыніца

16 адказы

Некаторыя людзі не могуць дазволіць сабе раскоша выкарыстоўваць станд :: вектар , нават з размеркавальніка. Некаторыя людзі маюць патрэбу ў масіў дынамічна памеру, так што станд :: масіў выходзіць. І некаторыя людзі атрымліваюць свае масівы з іншага кода, які, як вядома, вяртае масіў; і гэты код не будзе перапісаны, каб вярнуць вектар ці нешта.

By allowing unique_ptr, you service those needs.

In short, you use unique_ptr when you need to. When the alternatives simply aren't going to work for you. It's a tool of last resort.

197
дададзена
@MilesRout, @DanNissenbaum - Вы маглі б таксама мець API абмежаванні, як вы не можаце змяніць подпіс. Такім чынам, вы хочаце выкарыстоўваць аўтаматычны паказальнік для RIAA і бяспекі выключэнняў, і скончыць функцыю з Release() , каб вярнуць паказальнік на выклікае абанента. Код, які я гляджу робіць тое ж самае, таму што ён не можа зламаць API для знешніх абанентаў.
дададзена аўтар jww, крыніца
Мне цікава, калі каментар <�я> некаторыя праекты маюць вельмі спецыфічныя патрабаванні, і сярод іх могуць быць «вы не можаце выкарыстоўваць вектар » з'яўляецца чыста тэарэтычным, або калі гэта грунтуючыся на вядомых сітуацыях, і калі такое абмежаванне можа быць разумным.
дададзена аўтар Dan Nissenbaum, крыніца
Дарэчы ім не downvoter, хоць, як я сказаў, я лічу, раскоша быць няўдалае слова тут :) добры адказ у цэлым
дададзена аўтар NoSenseEtAl, крыніца
Добра, я бачу, я думаў, што раскоша вы мелі на ўвазе PErF меркаванні, а не невуцтва :)
дададзена аўтар NoSenseEtAl, крыніца
Позні да партыі, але іншы сцэнар, я быў нядаўна там, дзе я не хачу, каб змена памераў, але хацеў неконстантный доступ да аб'ектаў. А Const unique_ptr <�Т []> было рашэнне
дададзена аўтар baruch, крыніца
Я не думаю, што гэта пытанне аб тым, ці можа хто-то выкарыстоўваць зЬй :: вектар над станд :: unique_ptr наогул. Я выкарыстоўваю станд :: unique_ptr для некаторых масіваў, так як я магу быць упэўнены, што, калі выключэнне, гэта збіраецца быць ачышчаны належным чынам.
дададзена аўтар The Welder, крыніца
@DanNissenbaum Акрамя таго, некаторыя жорсткія сістэмы рэальнага часу не дазваляюцца выкарыстоўваць дынамічнае выдзяленне памяці наогул як затрымку сістэмнага выкліку, прычыны не могуць быць тэарэтычна абмежаванай, і вы не можаце даказаць, паводзіны ў рэальны час праграмы. Або адзнака можа быць занадта вялікі, які парушае свой ліміт WCET. Хоць тут непрыстасавальны, так як яны не будуць выкарыстоўваць unique_ptr альбо, але гэтыя віды праектаў сапраўды існуюць.
дададзена аўтар Emily L., крыніца
@DanNissenbaum існуюць гэтыя праекты. Некаторыя галіны прамысловасці, якія знаходзяцца пад вельмі жорсткім пільнай увагай, як, напрыклад, авіяцыі і абароны, стандартная бібліятэка па-за межамі, так як цяжка праверыць і даказаць, што гэта правільна тое, што кіруючы орган ўсталёўвае правілы. Вы можаце запярэчыць, што стандартная бібліятэка добра пратэставаная і я згодны з вамі, але вы і я не раблю правілы.
дададзена аўтар Emily L., крыніца
@MilesRout: Вы не можаце выкарыстоўваць вектар , калі T не капіяваць-построимых (напрыклад, push_back і emplace_back ня кампілюецца), але вы ўсё яшчэ можаце выкарыстоўваць unique_ptr .
дададзена аўтар Syncopated, крыніца
Я б сказаў, больш практычны прыклад будзе выкарыстоўваць функцыю, як: Foo (T * & buf_to_init)//выкарыстоўвае новы [], каб ініцыялізаваць паказальнік . У гэтым выпадку я магу абгарнуць гэты паказальнік ў unique_ptr пасля выкліку функцыі.
дададзена аўтар Ed S., крыніца
@Engineero: " даданне/выдаленне элементаў з станд :: вектар не ." На самой справе, гэта робіць. Да таго часу, пакуль вы бронируете досыць месцы для ўсіх элементаў, якія вы хочаце дадаць, вектар :: push_back будзе прымаць пастаяннае колькасць часу.
дададзена аўтар Nicol Bolas, крыніца
@Syncopated: FYI: Вы <�я> можна выкарыстоўваць вектар нават калі T не капіяваць-канструктыўныя. Вы не можаце <�я> выклік вектар :: push_back з такім T , але вы можаце найбольш вядома можна выкарыстоўваць вектар :: emplace_back </код >.
дададзена аўтар Nicol Bolas, крыніца
@NoSenseEtAl: Я не ўпэўнены, што частка «некаторыя людзі не могуць зрабіць гэта» выслізгвае вас. Некаторыя праекты маюць вельмі спецыфічныя патрабаванні, і сярод іх могуць быць «вы не можаце выкарыстоўваць вектар ». Можна сцвярджаць ці тыя разумныя патрабаванні ці не, але вы не можаце адмаўляць, што яны ёсць .
дададзена аўтар Nicol Bolas, крыніца
вось прычына, каб не выкарыстоўваць вектар: SizeOf (станд :: вектар <�сімвал>) == 24; SizeOf (станд :: unique_ptr <�сімвал []>) == 8
дададзена аўтар Arvid, крыніца
Адзіная прычына, каб не выкарыстоўваць вектар, калі вы не хочаце, каб аплаціць кошт кошту ініцыялізацыі масіва.
дададзена аўтар Charles Salvia, крыніца
У якасці прыкладу праекта, дзе «хоць і не будзе выкарыстоўваць станд :: вектар » з'яўляецца абавязковым патрабаваннем, я працаваў над праектам распрацоўкі праграмнага забеспячэння для ўбудавальных сістэм, для якіх мы не маглі выкарыстоўваць зЬй :: вектар з-за недетерминистическую дадання/выдалення часе (калі ён дынамічна змяняе сябе). У асноўным усе аперацыі неабходна прыняць вядомае, заўсёды паслядоўнае колькасць часу, і даданне/выдаленне элементаў з станд :: вектар ня робіць.
дададзена аўтар Engineero, крыніца
Добрае пытанне. Можа быць, гэта было даражэй ініцыялізацыя, ці толькі некаторыя хардкорных пераваг, перанесеныя з С, дыктавалі палітыку.
дададзена аўтар Engineero, крыніца
Шмат раней існавалі бібліятэк і OS API, прымае і выходныя дадзеныя з паказальнікамі на масівы. Часам памер не наканаваны, таму дынамічнае вылучэнне гэтага масіва патрабуецца. Калі ён, станд :: unique_ptr гэта выдатны спосаб зрабіць гэта выключэнне бяспекі.
дададзена аўтар VoidStar, крыніца
Там няма прычын у свеце, чаму хто-то не зможа выкарыстаць станд :: вектар калі яны могуць выкарыстоўваць зЬй :: unique_ptr .
дададзена аўтар Miles Rout, крыніца
Ці, калі вы хочаце, каб пераканацца, як пытанне палітыкі, што ніхто не забывае і ці зЬй :: рухацца і выпадкова копія </я> ўсю рэч. Хіба гэта не тое, які тып праверка для ??
дададзена аўтар Jimmy Hartzell, крыніца

Ёсць кампрамісы, і вы выбіраеце рашэнне, якое адпавядае таму, што вы хочаце. З верхняй частцы маёй галавы:

пачатковы памер

  • vector and unique_ptr allow the size to be specified at run-time
  • array only allows the size to be specified at compile time

змена памеру

  • array and unique_ptr do not allow змена памеру
  • vector does

захоўванне

  • vector and unique_ptr store the data outside the object (typically on the heap)
  • array stores the data directly in the object

капіраванне

  • array and vector allow капіраванне
  • unique_ptr does not allow капіраванне

Абмен/ход

  • vector and unique_ptr have O(1) time swap and move operations
  • array has O(n) time swap and move operations, where n is the number of elements in the array

Паказальнік/спасылка/итератор несапраўднасць

  • array ensures pointers, references and iterators will never be invalidated while the object is live, even on swap()
  • unique_ptr has no iterators; pointers and references are only invalidated by swap() while the object is live. (After swapping, pointers point into to the array that you swapped with, so they're still "valid" in that sense.)
  • vector may invalidate pointers, references and iterators on any reallocation (and provides some guarantees that reallocation can only happen on certain operations).

Сумяшчальнасць з паняццямі і алгарытмы

  • array and vector are both Containers
  • unique_ptr is not a Container

Я павінен прызнаць, што гэта выглядае як магчымасць для некаторага рэфактарынгу з дызайнам на аснове палітык.

95
дададзена
Я не ўпэўнены, я разумею, што вы маеце на ўвазе ў кантэксце <�я> паказальнік несапраўднасьці . Гэта пра ўказальнікі на самі аб'екты або паказальнікі на элементы? Ці нешта яшчэ? Якія гарантыі вы атрымліваеце ад масіва, што вы не атрымліваеце ад вектару?
дададзена аўтар jogojapan, крыніца
Добра, што не можа быць прызнанне несапраўднымі ў выніку пераразмеркавання ў масіве або unique_ptr <�Т []> , таму што няма ніякага пераразмеркавання. Але, вядома, калі масіў выходзіць з вобласці бачнасці, паказальнікі на канкрэтныя элементы ўсё роўна будуць прызнаныя несапраўднымі.
дададзена аўтар jogojapan, крыніца
Хоць unique_ptr не мае итератор убудаваны, вы ўсё яшчэ можаце перабіраць яго як звычайны T [] , што азначае, што вам патрэбен памер дыяпазону каб ітэрацыі.
дададзена аўтар rubenvb, крыніца
@Pseudonym Хоць гэта не можа тырчэць. Хоць ён павінен ведаць, як вызваліць памяць, якая даступная для новы [] эд масіў, гэта не на самай справе трэба вылучыць менавіта гэта. Гэта можа прамахнуцца для выраўноўвання памяці, яна можа падзяляць памяць з іншымі аб'ектамі ў блоку, які проста падлічвае колькасць блокаў, якія былі вылучаныя яго. Ці ён можа не рабіць нічога з гэтага. Сутнасць у тым, што размеркаванне можа быць зроблена ў многіх адносінах, і прымушаючы аллокатор адсочваць памер блока, які вы вылучаемы хоць лагічна не можа быць аптымальнымі. C ++ кажа, не плацяць за тое, што вы не выкарыстоўваеце.
дададзена аўтар Aidiakapi, крыніца
@Pseudonym Але гэта ні ў якім разе не азначае, што ён павінен мець гэтую інфармацыю лёгка даступнай. Як я ўжо сказаў, мой пункт гледжання не тое, што інфармацыя не існуе з большасцю бібліятэк размеркавальнікі/па змаўчанні, я проста сказаў, што гэта не павінна быць. AFAIK ў VC ++ памер фактычна як цэлае да масіва ў памяці, вы можаце літаральна атрымаць доступ да яго, але гэта нявызначаны паводзіны. Там могуць быць алгарытмы, якія там сапраўды ёсць інфармацыя, але доступ да яго будзе O (п), аналагічна даўжыні звязанага спісу або радкі ў стылі C. Аб (п) для даўжыні не з'яўляецца праблемай, так як разбурэнне Аб (п) у любым выпадку.
дададзена аўтар Aidiakapi, крыніца
У дадатак да гэтага, калі аб'ект з'яўляецца трывіяльным destructable, ён не павінен сачыць за даўжынёй на ўсіх, ён можа аптымізаваць гэта і проста захоўваць памер блока замест гэтага. Усё, што я спрабую сказаць, што гэта да размеркаванага вырашыць, што з'яўляецца эфектыўным, і прымушаючы аллокатор даць гэтую інфармацыю, нягледзячы на ​​тое, што ёсць шмат выпадкаў, дзе гэта не трэба, абмяжоўвае гэта.
дададзена аўтар Aidiakapi, крыніца
@Aidiakapi C ++ патрабуе, што калі выдаліць [] масіў аб'ектаў, якія маюць дэструктары, дэструктары атрымаць прабег. Па гэтай прычыне, C ++ час выканання ўжо павінна ведаць фактычны памер большасць масіваў, якія былі вылучаныя такім чынам. Цяпер, прыстойны C ++ рэалізацыі зрабіць аптымізацыі деструкторов, калі аб'екты ў масіве не маюць деструкторов (напрыклад, базавы тыпу) або деструктор, які нічога не робіць. Тым не менш, яны, як правіла, не аптымізаваць размеркаванне памяці для гэтага выпадку. Гэта можа адбыцца, але гэта не так. Таму інфармацыя аб памеры ёсць.
дададзена аўтар Pseudonym, крыніца
Усё, што я хачу сказаць, што ў пераважнай большасці выпадкаў рэалізацыя павінна захоўваць інфармацыю аб памеры масіва для правільнай рэалізацыі семантыкі C ++. Там няма прычын, чаму карыстальнік не можа атрымаць доступ да гэтай інфармацыі, і яна будзе па-ранейшаму прытрымлівацца правілу, што вы не плаціце за тое, што вы не выкарыстоўваеце.
дададзена аўтар Pseudonym, крыніца
@rubenvb Вядома, вы можаце, але вы не можаце (напрыклад) выкарыстоўваць дыяпазон на аснове для завес напрамую. Між іншым, у адрозненне ад звычайнага кода <> T [] , памер (ці эквівалентную інфармацыю) павінны быць тырчэць дзесьці аператара выдаліць [] правільна знішчыць элементы масіва. Было б добра, калі праграміст меў доступ да гэтага.
дададзена аўтар Pseudonym, крыніца
Так, усё стаўкі не гараць, калі аб'ект больш не жывуць.
дададзена аўтар Pseudonym, крыніца
Выкажам здагадку, што ў вас ёсць итератор, паказальнік або спасылку на элемент а вектар . Тады вы павялічыць памер або ёмістасць гэтага вектар такім чынам, што гэта выклікае пераразмеркаванне. Тады што итератор, паказальнік або спасылка больш не паказвае на гэты элемент вектар . Гэта тое, што мы маем на ўвазе пад «несапраўднасьці». Гэтая праблема не здараецца масіў , таму што няма «Пераразмеркаванне». На самай справе, я толькі што заўважыў дэталь з гэтым, і я рэдагаваў яго, каб задаволіць.
дададзена аўтар Pseudonym, крыніца

Адна з прычын, вы можаце выкарыстоўваць unique_ptr , калі вы не хочаце, каб аплаціць кошт падчас выканання значэнне ініцыялізацыя масіў.

std::vector vec(1000000);//allocates AND value-initializes 1000000 chars

std::unique_ptr p(new char[1000000]);//allocates storage for 1000000 chars

<�Код> станд :: вектар Канструктар і станд :: вектар :: памер() ацэніць ініцыялізацыю T - а новы не будзе рабіць, калі T з'яўляецца POD.

See Value-Initialized Objects in C++11 and std::vector constructor

Note that vector::reserve is not an alternative here: Is accessing the raw pointer after std::vector::reserve safe?

Гэта тая ж прычына, па якой C праграміст можа выбраць Таноса над calloc .

57
дададзена
Але гэтая прычына не адзінае рашэнне .
дададзена аўтар Ruslan, крыніца
яшчэ адна магчымасць заключаецца ў тым, каб даць станд :: вектар а прыстасаваныя Размеркавальнік , які дазваляе пазбегнуць будаўніцтва тыпаў якія станд :: is_trivially_default_constructible і знішчэнне аб'ектаў, станд :: is_trivially_destructible , хоць строга гэта парушае стандарт C ++ (паколькі такія тыпы ня па змаўчанні ініцыялізуюцца).
дададзена аўтар Walter, крыніца
Таксама станд :: unique_ptr не дае якой-небудзь межы праверкі насуперак шмат станд :: вектар рэалізацыямі.
дададзена аўтар diapir, крыніца
@Ruslan У звязаным растворы элементы дынамічнага масіва па-ранейшаму значэнне ініцыялізаваны, але значэнне ініцыялізацыі не робіць нічога. Я згодны, што Аптымізатар, які не разумее, што не робіць нічога 1000000 раз можа быць рэалізаваны без кода не варта ні капейкі, але адзін можа аддаць перавагу ня залежаць ад гэтай аптымізацыі наогул.
дададзена аўтар Marc van Leeuwen, крыніца

An std::vector can be copied around, while unique_ptr allows expressing unique ownership of the array. std::array, on the other hand, requires the size to be determined at compile-time, which may be impossible in some situations.

27
дададзена
@Yakk: Я не ведаю, як прыняць ваш каментар, гэта азначала, што-то выправіць у маёй абароне?
дададзена аўтар Andy Prowl, крыніца
@NicolBolas: Можа быць, вы зрабілі кропку ясна, і я проста не ў стане зразумець гэта. Я не кажу, што гэта абмежаванне вашага тлумачэння. Прабачце, калі я ўсё яшчэ вучуся, я проста хачу зразумець.
дададзена аўтар Andy Prowl, крыніца
@NicolBolas: Я думаў, што асноўная прычына для выкарыстання unique_ptr , а не shared_ptr ў тым, што адна мадэль унікальнай уласнасці, а іншай няма. Хоць гэта праўда, што unique_ptr мае нулявую нагрузку, я схільны бачыць уласнасці семантыкі ў якасці асноўнага дискриминанта тут.
дададзена аўтар Andy Prowl, крыніца
@NicolBolas: Я не разумею. Адзін можа спатрэбіцца, каб прадухіліць, што па той жа прычыне, чаму можна было б выкарыстоўваць unique_ptr замест shared_ptr . Ці магу я што-то адсутнічае?
дададзена аўтар Andy Prowl, крыніца
Хм, я павінен быў уключаць @NicolBolas ў ім. Я прачытаў каментары, і каментуючы іх. :)
дададзена аўтар Yakk - Adam Nevraumont, крыніца
<�Код> станд :: вектар мае больш накладных выдаткаў, чым станд :: unique_ptr - ён выкарыстоўвае паказальнікі ~ 3 замест ~ 1. <�Код> станд :: unique_ptr блокі скапіяваць канструкцыю, але дазваляе рухацца канструкцыю, калі семантычна дадзеныя вы працуеце з могуць быць перамешчаныя толькі, але не капіюецца, заражае класа , які змяшчае дадзеныя. Маючы аперацыю над дадзенымі, <�я> не зьяўляецца сапраўдным </я> на самой справе робіць ваш клас кантэйнер горш, і «проста не выкарыстоўваць яго" не змывае ўсе грахі. Маючы пакласці кожны асобнік вашага станд :: вектар у класе, дзе вы ўручную адключыць Перанесці з'яўляецца галаўным болем. <�Код> станд :: unique_ptr <�станд :: масіў> мае памер .
дададзена аўтар Yakk - Adam Nevraumont, крыніца
Проста таму, што нешта <�я> можна </я> капіявацца вакол не азначае, што гэта павінна быць.
дададзена аўтар Nicol Bolas, крыніца
<�Код> unique_ptr робіць больш, чым проста прадухіліць выпадковае няправільнае выкарыстанне. Гэта таксама менш і менш, чым накладныя выдаткі shared_ptr . Справа ў тым, што, у той час як добра мець семантыку ў класе, якія перашкаджаюць «няправільны», гэта не адзіная прычына, каб выкарыстоўваць пэўны тып. І вектар з'яўляецца значна больш карысным у якасці захоўвання масіва, чым unique_ptr , калі не па прычынах, акрамя таго, што яна мае памер </я>.
дададзена аўтар Nicol Bolas, крыніца
Я думаў, што я зрабіў пункт ясна: ёсць <�я> іншыя прычыны выкарыстоўваць пэўны тып, чым гэта. Гэтак жа, як ёсць прычыны аддаваць перавагу вектар над unique_ptr , дзе гэта магчыма, замест таго, каб проста сказаць, «Вы не можаце капіяваць яе» і, такім чынам, выбраць <�код > unique_ptr , калі вы не хочаце копіі. Прыпынак кагосьці рабіць няправільныя рэчы не абавязкова самая важная прычына, каб выбраць клас.
дададзена аўтар Nicol Bolas, крыніца
Heck, станд :: unique_ptr <�станд :: вектар>, магчыма, што вы шукаеце, калі вы хочаце унікальны паказальнік на дынамічна паўторна значны масіў.
дададзена аўтар Miles Rout, крыніца

Скот Мейерс гэта сказаць у эфектыўнай сучаснай C ++

The existence of std::unique_ptr for arrays should be of only intellectual interest to you, because std::array, std::vector, std::string are virtually always better data structure choices than raw arrays. About the only situation I can conceive of when a std::unique_ptr would make sense would be when you're using a C-like API that returns a raw pointer to a heap array that you assume ownership of.

I think that Charles Salvia's answer is relevant though: that std::unique_ptr is the only way to initialise an empty array whose size is not known at compile time. What would Scott Meyers have to say about this motivation for using std::unique_ptr?

18
дададзена
Падобна на тое, ён проста не ўявіць сабе некалькі варыянтаў выкарыстання, а менавіта буфер, памер якога з'яўляецца фіксаваным, але невядома, падчас кампіляцыі, і/або буфер, для якога мы не дазваляем копію. Там таксама эфектыўнасць у якасці магчымай прычыны аддаць перавагу яе вектар stackoverflow.com/a/24852984/2436175</а>.
дададзена аўтар Antonio, крыніца

У адрозненне ад станд :: вектар і станд :: масіў , станд :: unique_ptr можа належаць паказальнік NULL.
Гэта вельмі зручна пры працы з API, C, якія чакаюць альбо масіў або NULL:

void legacy_func(const int *array_or_null);

void some_func() {    
    std::unique_ptr ptr;
    if (some_condition) {
        ptr.reset(new int[10]);
    }

    legacy_func(ptr.get());
}
10
дададзена

A common pattern can be found in some Windows Win32 API calls, in which the use of std::unique_ptr can come in handy, e.g. when you don't exactly know how big an output buffer should be when calling some Win32 API (that will write some data inside that buffer):

// Buffer dynamically allocated by the caller, and filled by some Win32 API function.
// (Allocation will be made inside the 'while' loop below.)
std::unique_ptr buffer;

// Buffer length, in bytes.
// Initialize with some initial length that you expect to succeed at the first API call.
UINT32 bufferLength = /* ... */;

LONG returnCode = ERROR_INSUFFICIENT_BUFFER;
while (returnCode == ERROR_INSUFFICIENT_BUFFER)
{
   //Allocate buffer of specified length
    buffer.reset( BYTE[bufferLength] );
   //       
   //Or, in C++14, could use make_unique() instead, e.g.
    //
   //buffer = std::make_unique(bufferLength);
    //

    //
   //Call some Win32 API.
    //
   //If the size of the buffer (stored in 'bufferLength') is not big enough,
   //the API will return ERROR_INSUFFICIENT_BUFFER, and the required size
   //in the [in, out] parameter 'bufferLength'.
   //In that case, there will be another try in the next loop iteration
   //(with the allocation of a bigger buffer).
    //
   //Else, we'll exit the while loop body, and there will be either a failure
   //different from ERROR_INSUFFICIENT_BUFFER, or the call will be successful
   //and the required information will be available in the buffer.
    //
    returnCode = ::SomeApiCall(inParam1, inParam2, inParam3, 
                               &bufferLength,//size of output buffer
                               buffer.get(), //output buffer pointer
                               &outParam1, &outParam2);
}

if (Failed(returnCode))
{
   //Handle failure, or throw exception, etc.
    ...
}

// All right!
// Do some processing with the returned information...
...
9
дададзена

I have used unique_ptr to implement a preallocated memory pools used in a game engine. The idea is to provide preallocated memory pools used instead of dynamic allocations for returning collision requests results and other stuff like particle physics without having to allocate/free memory at each frame. It's pretty convenient for this kind of scenarios where you need memory pools to allocate objects with limited life time (typically one, 2 or 3 frames) that do not require destruction logic (only memory deallocation).

9
дададзена

У двух словах: гэта, безумоўна, найбольш эфектыўна выкарыстоўвае памяць.

A std::string comes with a pointer, a length, and a "short-string-optimization" buffer. But my situation is I need to store a string that is almost always empty, in a structure that I have hundreds of thousands of. In C, I would just use char *, and it would be null most of the time. Which works for C++, too, except that a char * has no destructor, and doesn't know to delete itself. By contrast, a std::unique_ptr will delete itself when it goes out of scope. An empty std::string takes up 32 bytes, but an empty std::unique_ptr takes up 8 bytes, that is, exactly the size of its pointer.

Самым вялікім недахопам з'яўляецца тое, кожны раз, калі я хачу ведаць даўжыню радка, я павінен назваць STRLEN на ім.

7
дададзена
Існуе станд :: вектар <�сімвал> тоже ..
дададзена аўтар Abhinav Gauniyal, крыніца

I faced a case where I had to use std::unique_ptr, which was in the HDF5 library (A library for efficient binary data storage, used a lot in science). Some compilers (Visual Studio 2015 in my case) provide compression of std::vector (by using 8 bools in every byte), which is a catastrophe for something like HDF5, which doesn't care about that compression. With std::vector, HDF5 was eventually reading garbage because of that compression.

Адгадайце, хто быў там для выратавання, у выпадку, дзе станд :: вектар не працуе, і мне трэба было вылучыць дынамічны масіў чыста? :-)

3
дададзена

Яны могуць быць самым правым адказ магчыма, калі вы атрымаеце толькі ткнуць адзін паказальнік праз існуючы API (думаюць, акно паведамленні або резьбонарезной звязаныя параметры зваротнага выкліку), якія маюць некаторую меру жыцця пасля таго, як «злавілі» на другім баку люка, але не мае ніякага дачынення да выклікаламу коду:

unique_ptr data = get_some_data();

threadpool->post_work([](void* param) { do_a_thing(unique_ptr((byte*)param)); },
                      data.release());

Мы ўсе хочам, каб усё было добра для нас. C ++ для іншых часоў.

2
дададзена
  • You need your structure to contain just a pointer for binary-compatibility reasons.
  • You need to interface with an API that returns memory allocated with new[]
  • Your firm or project has a general rule against using std::vector, for example, to prevent careless programmers from accidentally introducing copies
  • You want to prevent careless programmers from accidentally introducing copies in this instance.

Існуе агульнае правіла, што кантэйнеры C ++ павінны быць пераважней, чым прокатка Вашага ўласная з паказальнікамі. Гэта агульнае правіла; ён мае выключэнні. Там больш; гэта толькі прыклады.

2
дададзена

To answer people thinking you "have to" use vector instead of unique_ptr I have a case in CUDA programming on GPU when you allocate memory in Device you must go for a pointer array (with cudaMalloc). Then, when retrieving this data in Host, you must go again for a pointer and unique_ptr is fine to handle pointer easily. The extra cost of converting double* to vector is unnecessary and leads to a loss of perf.

2
дададзена

unique_ptr can be used where you want the performance of C and convenience of C++. Consider you need to operate on millions (ok, billions if you don't trust yet) of strings. Storing each of them in a separate string or vector object would be a disaster for the memory (heap) management routines. Especially if you need to allocate and delete different strings many times.

However, you can allocate a single buffer for storing that many strings. You wouldn't like char* buffer = (char*)malloc(total_size); for obvious reasons (if not obvious, search for "why use smart ptrs"). You would rather like unique_ptr buffer(new char[total_size]);

By analogy, the same performance&convenience considerations apply to non-char data (consider millions of vectors/matrices/objects).

1
дададзена

One additional reason to allow and use std::unique_ptr, that hasn't been mentioned in the responses so far: it allows you to forward-declare the array element type.

Гэта карысна, калі вы хочаце, каб мінімізаваць прыкаваны #include заявы ў загалоўках (для аптымізацыі прадукцыйнасці зборкі.)

Напрыклад -

<�Р> myclass.h:
class ALargeAndComplicatedClassWithLotsOfDependencies;

class MyClass {
   ...
private:
   std::unique_ptr m_InternalArray;
};
<�Р> myclass.cpp:
#include "myclass.h"
#include "ALargeAndComplicatedClassWithLotsOfDependencies.h"

// MyClass implementation goes here

З улікам названых вышэй структуры кода, любы можа #include «myclass.h» і выкарыстоўвайце MyClass , без неабходнасці ўключэння ўнутраных залежнасцяў рэалізацыі патрэбных MyClass :: m_InternalArray .

If m_InternalArray was instead declared as a std::array, or a std::vector<...>, respectively - the result would be attempted usage of an incomplete type, which is a compile-time error.

1
дададзена
Для гэтага канкрэтнага выпадку выкарыстання, я выбраў бы шаблон Pimpl разарваць залежнасць - калі яна выкарыстоўваецца толькі ў прыватным парадку, то вызначэнне можа быць адкладзена да тых часоў, метады класа не рэалізуюцца; калі ён выкарыстоўваецца публічна, то карыстальнікі класа павінны мець ўжо мелі канкрэтныя веды аб клас ALargeAndComplicatedClassWithLotsOfDependencies . Так лагічна вы не павінны працаваць у такія сцэнары.
дададзена аўтар Pigpag, крыніца

Калі вам патрэбен дынамічны масіў аб'ектаў, якія не капіруе-канструктыўна, то разумны паказальнік на масіў з'яўляецца шляхам. Напрыклад, што калі вам патрэбен масіў Атомикс.

0
дададзена