a
- это глобальный объект со статической продолжительностью хранения, поэтому он будет инициализирован в некотором заранее выделенном хранилище где-то до выполнения тела main. Если предположить, что вызов Test не является результатом какой-то странности конструкции статического объекта, a
будет полностью построен к моменту вызова Test.
a = new A;
Это немного необычное присваивание не будет (только) стандартной операцией присваивания копии, поскольку вы назначаете указатель на A
на a, а не на объект или ссылку. Собирается ли он на самом деле и что именно он вызывает, зависит от того, есть ли у A
оператор присваивания, который принимает указатель на A
, или что-то неявно конвертируемое из указателя на A
, или есть ли у A
неявный конструктор, который принимает указатель на A
(или указатель на базовый класс A
).
Разместите редактирование, ваш код делает нечто иное!
Концептуально это выглядит примерно так:
A *tmpa;
void *mem = ::operator new( sizeof(A) ); // ( or possibly A::operator new )
try
{
tmpa = new (mem) A; // placement new = default constructor call
}
catch (...)
{
::operator delete( mem );
throw;
}
a = tmpa; // pointer assignment won't throw.
Опасность написания чего-то вроде этого заключается в том, что вы неявно добавляете много точек последовательности, которых просто нет в оригинале, и, кроме того, компилятору разрешено генерировать код, который не выглядит так, пока он ведет себя "как если бы" это было написано этим, насколько могла определить исполняющая программа. Это правило «как если бы» применяется только к исполняющемуся потоку, поскольку (текущий) язык ничего не говорит о работе взаимодействия с другими потоками.
Для этого вам необходимо использовать определенные гарантии поведения (если таковые имеются), предоставляемые вашей реализацией.
person
CB Bailey
schedule
17.06.2009