Дзе я павінен змяніць памер вэктару ў C ++

I have a very simple question: when we use the vector std::vector as the reference parameter of a function, should we resize the vector before calling the function or resizing the vector inside the function (suppose the size of the vector can be determined before hand? I give the following example to illustrate my question:

void fun1(std::vector ¶)
{
  para[0] = 1;
  para[1] = 2;
  ....
  para[10] = 11;

}
void fun2(std::vector ¶)
{
  para.resize(11);
  para[0] = 1;
  para[1] = 2;
  ...
  para[10] = 11;
}

Калі мы выклікаем fun1, мы выкарыстоўваем наступныя коды:

std::vector mypara;
mypara.resize(11);
fun1(mypara);

Калі мы выклікаем fun2, мы выкарыстоўваем наступныя коды:

std::vector mypara;
fun2(mypara);
1
Я б сказаў, што заўсёды ў функцыі ... канчатковы карыстальнік не мае магчымасцяў даведацца, што fun1 патрабуе 11 доўгага вектара (калі яны не чытаць вашыя каментары), а таксама накладныя выдаткі, змяненне памеру адной і той жа або меншы вектар даволі малыя. Як агульнае правіла для праграмавання: чалавек, які павінен будзе падтрымліваць ваш код ідыёт. Гэта асабліва актуальна, калі вы павінны падтрымліваць свой уласны код.
дададзена аўтар IdeaHat, крыніца

6 адказы

... Вы, напэўна, трэба проста вярнуць вектар.

std::vector fun3()
{
  std::vector para(11);
  para[0] = 1;
  para[1] = 2;
  ...
  para[10] = 11;
  return para;
}

Я ведаю, што адчувае сябе не так, але C ++/STL на самай справе вельмі разумны аб такім родзе рэч. Гэта на самай справе не выпісваць пункт, ён будзе рабіць канструктар перамяшчэння/зрабіць вяртаецца значэнне optomization, а не канструктар капіявання.

http://cpp-next.com/archive/ 2009/08/купля хуткасць абмінуць па значэнні/

3
дададзена
@juanchopanza пра тое, што гэта выдатнае, дадаў, што да адказу.
дададзена аўтар IdeaHat, крыніца
Што, хутчэй за ўсё, адбудзецца гэта вяртанне значэння аптымізацыя, якая працуе да C ++ 11 і не патрабуе перасоўванне канструктараў у C ++ 11.
дададзена аўтар juanchopanza, крыніца
РВО азначае, што ваш WARNING звычайна няправільна.
дададзена аўтар juanchopanza, крыніца

Проста выкарыстоўвайце push_back і хай вектар зрабіць сябе змяненне памеру, калі неабходна:

std::vector mypara;
mypara.push_back(1);
...
mypara.push_back(11);

Калі вы ведаеце, колькі элементаў будзе ўпісвацца ў ваш вектар можна назваць Рэзерв перад даданнем элементаў або ўсталяваць пачатковы памер у якасці параметраў:

std::vector mypara(10);//Be aware that this will create 10 elements!
//or...
std::vector mypara;
mypara.reserve(10);//This will set the size, but there won't be any elements in it yet.

Пачатковы памер вектара з'яўляецца дастаткова вялікім для большасці выпадкаў, і гэта не будзе змяняць памер вельмі часта. Але часам гэта можа прывесці да праблемы, калі вы дадаеце толькі адзін элемент, і ён атрымлівае змяніць на шляху большага памеру. У гэтым выпадку, выкарыстоўваючы рэзерв можа павысіць прадукцыйнасць таксама.

Але калі ў вас ёсць, каб зрабіць змяненне памеру, зрабіць гэта ў функцыі ў вашым выпадку. Гэта больш зразумела чытачу кода, і гэта можна ўбачыць, што вы маюць намер. Трымаеце аб'ём невялікі.

3
дададзена
Я таксама згодны з дапамогай push_back замест індэксацыі ў вектар. Аднак, у залежнасці ад рэальнага колькасці элементаў можа быць цікава для выкліку </рэзервовы код> (не змяніць памер заўважце) загадзя.
дададзена аўтар syam, крыніца
Дзякуй за парады, хлопцы. Я абнавіў адказ.
дададзена аўтар Skalli, крыніца
Майце на ўвазе, што гэты падыход можа ўкусіць. Напрыклад, калі ў вас ужо ёсць 1024 элементаў і трэба проста яшчэ адзін вектар можа, а памер да 2048 і памяці адходаў коштам 1023 элементаў.
дададзена аўтар user405725, крыніца

І правільна, хоць fun2 здаецца трохі бяспечней. Вы можаце скапіяваць яго ў іншы праект, і ён будзе працаваць нармальна, у адрозненне ад fun1, што патрабуе пункт, каб мець памер correclty загадзя.

2
дададзена

Вы б не звычайна відавочна змяніць памер вектар наогул - ні ў выкліку функцыі, ні перад выклікам функцыі. <�Код> вектар кіруе сваім уласным выкарыстанне памяці, і расце па меры неабходнасці для размяшчэння новых элементаў.

Ёсць абставіны, пры якіх вы будзеце дадаваць грыва элементы і не хочаце пакутаваць шматлікае пераразмеркаваннем вектара па меркаваннях прадукцыйнасці. Гэта звычайна адбываецца толькі ў «гарачай шляху» вашага прыкладання, а не для кожнага прыкладання. У гэтых параўнальна рэдкіх выпадках, функцыя, якая дадае элементы павінны несці адказнасць за enusring дастатковай ёмістасці ў вектары. Каб зрабіць гэта, вы не карыстаецеся змяніць памер , але </рэзервовы код>. Абодва будуць пераразмяркоўваць вектар калі necesarry (і, такім чынам, несапраўднымі итераторы, так што будзьце асцярожныя), але змяніць памер фактычна змяняе botht кнопку памер() і <�код > ёмістасць() аб вектар , а рэзерв змяняе толькі ёмістасць() .

Каб зразумець розніцу:

vector  v;
v.reserve (10);
copy (v.begin(), v.end(), ostream_iterator (cout, ","));

Вышэй выхад будзе нічога, таму што няма нічога "в" вектар , нават калі няма месца для 10 элементаў. аднак:

vector  v;
v.resize (10);
copy (v.begin(), v.end(), ostream_iterator (cout, ","));

Гэты код будзе выводзіць 10 па змаўчанні узведзенага Int с. Ёсць 10 элементаў у масіве. Калі вы змена памеру() а вектар проста, каб вызваліць месца для новых элементаў, памер() , верагодна, не тое, што вы хочаце зрабіць.

2
дададзена

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

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

1
дададзена

Калі функцыя мае патрабаванні да ўваходнага вектару, не выкарыстоўвае свае дадзеныя, і мяркуецца, што гэта overwriteable, то гэта можа быць лепш проста вярнуць вектар па значэнні:

std::vector fun()
{
  std::vector v(11);
  std::iota(v.begin(), v.end(), 1);
  return v;
}

Такім чынам, абанент не павінен турбавацца пра тое, што павінна быць стан уваходнага вэктару, а функцыя не рабіць якія-небудзь праверкі на вектар.

1
дададзена