defer
является логическим атрибутом [HTML 4.01 spec] :
Некоторые атрибуты играют роль булевых переменных (например, атрибут
selected
для элементOPTION
). Их появление в начале тега элемента подразумевает, что значение атрибута «истинно». Их отсутствие подразумевает значение «false».[...]
В HTML логические атрибуты могут отображаться в минимизированной форме - значение атрибута появляется только в начале элемента тег. Таким образом,
selected
может быть задан путем записи:вместо:
Авторы должны знать, что многие пользовательские агенты распознают только минимизированную форму логических атрибутов а не в полной форме.
Однако, если вы используете XHTML, вам нужно использовать вторую форму, поскольку XHTML следует синтаксису XML, где атрибуты всегда должны иметь значение.
Когда мне нужно объявить их самостоятельно?
blockquote>Правило трех утверждает, что если вы объявляете какой-либо из конструкторов копии
- оператор присваивания копии
- destructor
, тогда вы должны объявить все три. Из наблюдений выяснилось, что необходимость использовать смысл операции копирования почти всегда вытекает из класса, выполняющего какое-то управление ресурсами, и это почти всегда подразумевает, что
- независимо от управления ресурсами выполнялось в одной операции копирования, возможно, необходимо было выполнить в другой операции копирования, а
- деструктор класса также будет участвовать в управлении ресурсом (обычно его освобождая). Классическим ресурсом для управления была память, поэтому все классы стандартной библиотеки, которые управляют памятью (например, контейнеры STL, которые выполняют управление динамической памятью), объявляют «большую тройку»: обе операции копирования и деструктор.
Следствием правила трех является то, что присутствие объявленного пользователем деструктора указывает на то, что простая копия элемента с несколькими членами вряд ли будет подходящей для операций копирования в классе. Это, в свою очередь, предполагает, что если класс объявляет деструктор, операции копирования, вероятно, не должны автоматически генерироваться, потому что они не будут поступать правильно. В то время, когда C ++ 98 был принят, значение этой линии рассуждений не было полностью оценено, поэтому в C ++ 98 существование объявленного пользователем деструктора не повлияло на готовность компиляторов генерировать операции копирования. Это все еще имеет место в C ++ 11, но только потому, что ограничение условий, при которых выполняются операции копирования, приведет к сломанию слишком большого количества устаревшего кода.
Как я могу предотвратить, чтобы мои объекты не были скопировано?
blockquote>Объявить конструктор копирования & amp; оператор присваивания копии в качестве спецификатора частного доступа.
class MemoryBlock { public: //code here private: MemoryBlock(const MemoryBlock& other) { cout<<"copy constructor"<<endl; } // Copy assignment operator. MemoryBlock& operator=(const MemoryBlock& other) { return *this; } }; int main() { MemoryBlock a; MemoryBlock b(a); }
В C ++ 11 вы также можете объявить конструктор копирования & amp; оператор присваивания удален
class MemoryBlock { public: MemoryBlock(const MemoryBlock& other) = delete // Copy assignment operator. MemoryBlock& operator=(const MemoryBlock& other) =delete }; int main() { MemoryBlock a; MemoryBlock b(a); }
Правило of Three является правилом для C ++, в основном говоря
Если вашему классу требуется любой из
- конструктор копирования,
- оператор присваивания,
- или деструктор,
определенно, тогда, вероятно, все три из них .
blockquote>Причины этого в том, что все три из них обычно используются для управления ресурсом, и если ваш класс управляет ресурсом, ему обычно необходимо управлять копированием, а также освобождать.
Если для копирования ресурса, который ваш класс управляет, нет хорошей семантики, тогда подумайте о том, чтобы запретить копирование, объявив (не , определяющий ) конструктор копирования и оператор присваивания как
private
.(Обратите внимание, что предстоящая новая версия стандарта C ++ (которая является C ++ 11) добавляет семантику перемещения в C ++, что, скорее всего, изменит правило из трех. Однако я слишком мало знаю об этом напишите раздел C ++ 11 о правиле трех.)
boost::noncopyable
). Это также может быть намного яснее. Я думаю, что C ++ 0x и возможность «удалить» функции могут помочь здесь, но забыл синтаксис: /
– Matthieu M.
13 November 2010 в 17:33
noncopyable
не является частью std lib, я не считаю это существенным улучшением. (О, и если вы забыли синтаксис удаления, вы забыли mor ethan, который я когда-либо знал. :)
)
– sbi
13 November 2010 в 18:20
Закон большой тройки такой, как указано выше.
Легкий пример на простом английском языке той проблемы, которую он решает:
Неисправный деструктор
]Вы выделили память в своем конструкторе, и вам нужно написать деструктор, чтобы удалить его. В противном случае произойдет утечка памяти.
Вы можете подумать, что это работа.
Проблема будет, если копия сделана из вашего объекта, то копия укажет на ту же память, что и на исходный объект.
Однажды один из них удаляет память в своем деструкторе другой будет иметь указатель на недопустимую память (это называется обвисший указатель), когда он пытается использовать его, все будет выглядеть волосатым.
Поэтому вы пишете конструктор копирования, чтобы он выделяет новые объекты для уничтожения своих собственных фрагментов памяти.
Оператор присваивания и конструктор копирования
Вы выделили память в своем конструкторе указателю участника вашего класса. Когда вы копируете объект этого класса, оператор присваивания по умолчанию и конструктор копирования копируют значение этого элемента-указателя на новый объект.
Это означает, что новый объект и старый объект будут указывать на тот же кусок памяти, поэтому, когда вы меняете его на один объект, он будет изменен и для другого объекта objerct. Если один объект удаляет эту память, другой будет продолжать пытаться ее использовать - eek.
Чтобы решить эту проблему, вы пишете собственную версию конструктора копирования и оператора присваивания. Ваши версии выделяют отдельную память новым объектам и копируют значения, на которые указывает первый указатель, а не его адрес.
В принципе, если у вас есть деструктор (а не деструктор по умолчанию), это означает, что класс, который вы определили, имеет некоторое распределение памяти. Предположим, что класс используется снаружи каким-либо клиентским кодом или вами.
MyClass x(a, b);
MyClass y(c, d);
x = y; // This is a shallow copy if assignment operator is not provided
Если MyClass имеет только некоторые примитивные типизированные члены, то оператор присваивания по умолчанию будет работать, но если он содержит некоторые элементы и объекты указателя не имеют операторов присваивания, результат будет непредсказуемым. Поэтому мы можем сказать, что если в деструкторе класса есть что-то удалить, нам может понадобиться оператор глубокой копии, что означает, что мы должны предоставить конструктор копирования и оператор присваивания.
Правило из трех в C ++ является основополагающим принципом проектирования и разработки трех требований, которые, если в одной из следующих функций-членов есть четкое определение, тогда программист должен определить две другие функции-члены вместе. А именно, необходимы следующие три функции-члена: деструктор, конструктор копирования, оператор присваивания копии.
Конструктор копирования в C ++ является специальным конструктором. Он используется для создания нового объекта, который является новым объектом, эквивалентным копии существующего объекта.
Оператор присваивания копии является специальным оператором присваивания, который обычно используется для указания существующего объекта другим пользователям тот же тип объекта.
Быстрые примеры:
// default constructor
My_Class a;
// copy constructor
My_Class b(a);
// copy constructor
My_Class c = a;
// copy assignment operator
b = a;
Многие уже существующие ответы уже касаются конструктора копирования, оператора присваивания и деструктора. Тем не менее, в post C ++ 11 введение семантики перемещения может расширить это за пределы 3.
Недавно Майкл Клайс произнес разговор, затрагивающий эту тему: http://channel9.msdn.com / события / CPP / CPP-Con-2014 / The-Canonical класса