Я читал о том, как оптимизация копирования и возвращаемое значение могут улучшить скорость, избегая обращений к конструктору копирования объектов. Я понимаю, как работают механизмы, но мне было интересно, не может ли это привести к программам, которые ведут себя не так, как следовало ожидать.
По сути, мой вопрос таков; что произойдет, если мы напишем конструктор копирования, чтобы не создавать объект, который является копией другого объекта? Другими словами, что если
AClass original;
AClass copy ( original );
// copy == original -> false
Скажем, например, у нас был такой класс:
// AClass.hpp
struct AClass
{
static int copyCount;
int copyNumber;
AClass():copyNumber(0){}
AClass( AClass const& original ):copyNumber(++copyCount){} // I think this is the signature for the copy constructor
};// AClass.cpp
int AClass::count ( 0 );
Это, очевидно, ужасное поведение, чтобы положить в класс, я не говорю, что я бы сделал что-то подобное. Суть, однако, стоит; что если мы полагаемся на побочные эффекты копии? В этом примере мы отслеживаем, сколько копий мы сделали. Я ожидаю, что оптимизация не должна влиять на работу программы. Однако копирование elision может привести к сбою следующего кода:
// Main.cpp
AClass MakeAClass()
{
return AClass();
}
int main()
{
AClass copy ( MakeAClass() );
if ( AClass::copyCount == 1 )
{
return 0;
}
else
{
return -1;
}
}
Это может вернуть 0, когда я строю в режиме отладки без оптимизаций, но внезапно завершится неудачей, когда я включу оптимизации, и возврат из MakeAClass будет помещен непосредственно в копию, пропуская конструктор копирования.
Есть ли проверка, когда компилятор пытается эти оптимизации искать побочные эффекты? Неправильно ли ожидать, что код выполнит копирование, когда вы запрашиваете копию?
Да. Elision Copy может изменить поведение вашего кода, если ваш конструктор копирования (или ваш конструктор перемещения или ваш деструктор) имеет побочные эффекты.
В этом весь смысл. Если бы это не могло изменить поведение, не было бы никакой причины упоминать это в стандарте. Оптимизации, которые не меняют поведение, уже охватываются правилом «как будто». (1.9 / 1) То есть:
Семантические описания в этом международном стандарте определяют
параметризованная недетерминированная абстрактная машина. Этот международный
Стандарты не предъявляют никаких требований к структуре соответствия
Реализации. В частности, им не нужно копировать или эмулировать
структура абстрактной машины. Скорее, соответствующие реализации
должны эмулировать (только) наблюдаемое поведение абстрактного
машина как объяснено ниже.
Исключение копирования прямо указано в стандарте именно потому, что оно потенциально нарушает это правило.
Других решений пока нет …