Якая розніца паміж абвяшчаючы канструктар прыватных і = выдаліць?

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

Абодва наступных дзвюх не дапускае выкарыстанне канструктара копіі:

<�Моцны> 1.

class Track
{
public:
  Track(){};
  ~Track(){};
private:
  Track(const Track&){};
};

<�Моцны> 2.

class Track
{
public:
  Track(){};
  ~Track(){};
  Track(const Track&)=delete;
};

<�Моцны> Ці з'яўляецца адзін з гэтых спосабаў «больш правільным», чым іншы, ці роўныя? Ці ёсць пабочны эфект?

//Does not compile with both the above ways
int main()
{
  Track l;
  Track p(l);
}
15
@EdHeal так, гэта робіць. г ++ 4.7
дададзена аўтар Avraam Mavridis, крыніца
Гэта не для "рэальнай" коды, толькі для скажам Academical прычыны, я хацеў бы ведаць, калі ёсць якой-небудзь пабочны эфект, ці што больш выкарыстоўваецца.
дададзена аўтар Avraam Mavridis, крыніца
<�Код> Выдаліць варыянт C ++ 11, і робіць мэта ясная. Што тычыцца іншых тэхнічных адрозненняў, ці сапраўды вы так? (Гэта, верагодна, уключае ў сябе некаторыя даволі жорсткія секцыі стандарту З ++, якія, верагодна, не робяць ніякай розніцы для вашага прыкладання).
дададзена аўтар juanchopanza, крыніца
гэта кампіляваць Ці Track (канстантнасцю Track &) = выдаліць; ???
дададзена аўтар Ed Heal, крыніца
Не бачыў такога выкарыстання Выдаліць раней. пашырэнне мовы? Калі так, то чым першы, безумоўна, з'яўляецца «больш правільным»
дададзена аўтар kotlomoy, крыніца

7 адказы

Стварэнне гэтага прыватнага «стары» спосаб зрабіць гэта. Канструктар па-ранейшаму існуе, але ён з'яўляецца прыватным, і можа быць выкліканы толькі з іншай функцыі-члена класа.

= delete deletes the constructor. It is not generated by the compiler, and it simply will not exist.

Так што, хутчэй за ўсё, = выдаліць з'яўляецца тое, што вы хочаце. (Хоць і з агаворкай, што не ўсе кампілятары падтрымліваюць гэты сінтаксіс яшчэ, таму, калі партатыўнасць неспакой ...)

15
дададзена

Абвясціўшы канструктар капіявання прыватны яшчэ дазваляе функцыі-члены Track клас для капіявання пабудаваць асобнікі гэтага класа, у той час як робіць яго выдалілі проста забараняе капіраванне пабудовы гэтага аб'екта.

In C++11, deleting a copy constructor is the right way to express the fact that a class is non-copyable (unless of course it makes sense for you to let member functions of Track, or friends of Track, to copy-construct Track objects).

7
дададзена

Стварэнне канструктар прыватных быў у асноўным «ўзламаць» у старым C ++, так як гэта быў адзіны спосаб, каб забараніць карыстальнікам выкарыстоўваць іх. Магчымасць Выдаліць спецыяльныя функцыі членаў быў уведзены толькі ў C ++ 11, і гэта лепш і больш ідыёматычны спосаб сказаць, што клас не можа быць скапіяваны. бо гэта відавочна аб <�намерах/EM>.

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

5
дададзена

Калі вы на C ++ 11, выкарыстоўвайце Выдаліць . Прычына заключаецца ў тым, што яна робіць выклік відавочным і намер ясна. Можна яшчэ выпадкова выкарыстоўваць прыватны канструктар (напрыклад, у абмежаванай наборы абласцей), але кампілятар будзе забараняць вам калі-небудзь з дапамогай аддаленага канструктара.

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

If your necessary toolchains do not support deleted constructors (= delete), you should not define it (as seen in your question) -- only declare it and leave it undefined, e.g.: private: \n Track(const Track&);

0
дададзена

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

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

Другі падыход робіць намер відавочным і тое, што вы павінны аддаваць перавагу, калі вы можаце выкарыстоўваць C ++ 11.

0
дададзена

Ваша першае рашэнне перадае чытачу, што копія-канструктар з'яўляецца прыватным і не будзе выкарыстоўвацца. Ваша другое рашэнне справядліва толькі ў C ++ 11. З-за гэтага, я б сказаў, больш пераносная і чытэльная рэалізацыя будзе вашым першай, выкарыстоўваючы прыватнаўласніцкія.

0
дададзена

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

У другім выпадку сінтаксіс забараняе копія робіцца. Гэта C ++ родны.

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

Вы можаце проста выкарыстоўваць «= выдаліць» і ясна азначае, што вы спрабуеце зрабіць.

0
дададзена