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.
写出这样的东西的危险在于,您隐式添加了许多原始序列中不存在的序列点,此外,编译器允许生成看起来不像这样的代码,只要它的行为就执行程序可以确定的情况而言,“好像”它是由 this 编写的。这个“好像”规则仅适用于正在执行的线程,因为(当前)语言没有说明与其他线程的交互是否有效。
为此,您需要使用您的实现提供的特定行为保证(如果有)。