Може ли член, който не може да се копира, да се използва като алтернатива, за да се направи обект неподлежащ на копиране?

Казва се, че клас с член, който не може да се копира, също не може да се копира. От SO, за да направите клас неподлежащ на копиране, това са опциите:

  1. Използвайте boost::noncopyable
  2. Декларирайте конструктора и оператора за присвояване като частни.
  3. Изтриване на конструктора за копиране.

    class foo 
    {
        private:
          std::mutex _dummy;
    };
    

Въпрос: Ще се използва ли включването на фиктивен некопируем член за подобна цел и за опростяване? Какви са недостатъците?


person ark1974    schedule 29.09.2018    source източник
comment
Вие маркирахте този въпрос C++11. Има ли някаква причина, поради която не можете просто да = delete конструктора за копиране?   -  person Nicol Bolas    schedule 29.09.2018
comment
@NicolBolas: Благодаря, добавям това.   -  person ark1974    schedule 29.09.2018
comment
Ще се използва ли включването на фиктивен некопируем член за подобна цел и за опростяване? Какви са недостатъците? - Не, не е достатъчно. Можете да напишете конструктор за копиране, който да не прави нищо по въпроса.   -  person max66    schedule 29.09.2018
comment
Винаги казвайте това, което имате предвид - добавянето на обект, който не може да се копира (особено нещо като mutex) просто обърква вашия код. Просто изтрийте конструктора за копиране и вероятно оператора за присвояване.   -  person    schedule 29.09.2018
comment
@max66 Да, достатъчно е, просто не е желателно.   -  person    schedule 29.09.2018
comment
@NeilButterworth - Може би трябва да кажа, че не е достатъчно... Искам да кажа: човек може да напише клас с елемент, който не може да се копира, и конструктор за копиране, който не копира стойността му. Така че обектът може да се копира и съдържа член, който не може да се копира. Знам: глупаво. По същата причина направете конструктора за копиране и operator=() private не е достатъчно, защото можете да направите функция friend към класа и класът да стане копируем (вътре във функцията friend).   -  person max66    schedule 29.09.2018


Отговори (1)


От C++11 насам правилният идиом за превръщане на класа в некопируем е = delete конструктора за копиране/оператора за присвояване. Това е, което C++ програмистите трябва да правят и това е, което другите C++ програмисти ще очакват да видят, когато търсят това поведение във вашия клас.

Добре е да имате подобект (член или базов клас), който не може да се копира, и по този начин вашият конструктор за копиране/оператор за присвояване по подразбиране ще бъде имплицитно изтрит. Но трябва да правите това само за подобект, който е случайно да не може да се копира. Тоест имате unique_ptr<T> или mutex или каквото и да е като член, защото имате нужда от unique_ptr<T> или mutex като данни за екземпляр на клас. Не защото го използвате като хак, за да направите типа невъзможен за копиране.

Недостатъците на използването на подобект член за тази цел са:

  1. Това обърква значението на вашия код. Вашият mutex _dummy; пример ми казва, че вашият тип има mutex в него. Ако нищо никога не използва тази променлива, тогава това ми казва, че вашият код е доста непоследователен; ако нямате нужда от подобект, не декларирате такъв. = delete е правилният идиом, така че трябва да го използвате.

  2. boost::noncopyable беше идиома на C++98/03, защото беше празен клас. И по този начин общата празна базова оптимизация би гарантирала, че няма да заема място в производния клас. Празните членове не получават такава оптимизация, така че член boost::noncopyable винаги ще прави вашия клас по-голям, без никаква полза. И докато можете да посочите предстоящия атрибут C++20 [[no_unique_address]], вижте причина #1.

person Nicol Bolas    schedule 29.09.2018