对通过get()获得的unique_ptr原始指针执行reset()是未定义的行为,就像:
std::unique_ptr<int> thing(new int(8));
int* other = thing.get();
other.reset(new int(15));
但是,如果unique_ptr的原始指针可以指向相同类型的对象怎么办?例如给出以下代码
class Node {
public:
std::unique_ptr<Node> previous;
std::unique_ptr<Node> next;
int data;
Node(int d) : previous(nullptr),
next(nullptr),
data(d) {}
};
void some_function(std::unique_ptr<Node> node, Node* other_ptr) {
Node* node_ptr = node.get();
node_ptr->next.reset(other_ptr); // ***
………………………………………………………………………………….
………………………………………………………………………………….
// Some code. Please don't focus on the secondary things.
// The main question whether it allowed to perform reset from line ****)
}
这也是未定义的行为吗?如果是,为什么。
代码链接:Code
答案 0 :(得分:2)
在以下前提条件下,some_function
的行为得到了很好的定义:
other_ptr
必须已经使用new
进行了分配,并且仍然有效(未删除)。other_ptr
的所有权必须已经转移 1 到该函数,即没有其他所有权。node
不能为空。但是,node
与所有参数一样,是函数的局部变量。函数结束时,node
被销毁。因此,它管理的指针将被删除。因此,修改指向的对象似乎是毫无意义的,这就是函数的作用。
1 使用裸指针转移所有权是一个坏主意。相反,您应该使用唯一的指针来转移所有权。
P.S。使用next
和previous
指针,Node
看起来很像一个双向链接列表。但是,它不能是列表,因为上一个节点和下一个节点可能都不能对当前节点拥有唯一的所有权。
P.P.S。 Node* node_ptr = node.get(); node_ptr->next.reset...
可以简化为node->next.reset
。