注意代码
...
{
int* p = new int(0);
std::unique_ptr<int> q(p);
...
// make use of 'p'
}
...
在上面的代码中,唯一指针q仅用于在时间到来时释放pQ本身不使用
由于q从未在声明行下方使用,因此它似乎可以在声明后立即释放,从而利用p"免费后使用">
问题是q保证一直存在,直到超出当前范围,或者编译器的优化器之前可以自由释放它?
使用"好像"规则,只要可观察的行为相同,编译器就可以进行任何优化。
不允许立即释放q
/p
,因为这样您将使用悬挂指针。
尽管它可以在作用域结束前调用析构函数:
{
int* p = new int(0);
std::unique_ptr<int> q(p);
...
// make use of 'p'
...
// No longer use of p (and q)
...
// Ok, can delete p/q now (as long there are no observable behaviors changes)
...
}
由于operator new
/delete
可能会被全局更改,编译器通常不会有足够的信息(尽管链接器有(,所以考虑它们有(潜在的(可观察的行为(作为任何外部函数(。
c++14允许对新表达式进行一些省略/优化,因此
{
delete new int(42);
int* p1 = new int(0);
int* p2 = new int(0);
std::unique_ptr<int> q2(p2);
std::unique_ptr<int> q1(p1);
...
// make use of 'p1'/p2
...
}
可以被"取代">
{
// delete new int(42); // optimized out
std::unique_ptr<int[]> qs{new int [] {0, 0}}; // only one allocation instead of 2
int* p1 = q->get();
int* p2 = q->get() + 1;
...
// make use of 'p1'/p2
...
}
我已经实现了自己问题的答案:
在代码中
{
int* p = new int(0);
std::unique_ptr<int> q(p);
...
// HERE
}
q的析构函数保证在作用域退出时调用(HERE(
虽然编译器可以随心所欲地为变量分配和释放寄存器,但析构函数保证在特定的位置-作用域出口中调用
我怎么知道
因为这是启用C++作用域保护的原因。通常,作用域保护用于在作用域退出时释放互斥对象——这是需要保证的。