试图引用已删除函数的唯一指针
Unique Pointer attempting to reference a deleted function
你好,我正在尝试使用指针,并学习C++
中唯一指针的基础知识。下面是我的代码,我在主函数中评论了这行代码。调试问题但是,我无法这样做。我缺少什么?insertNode()
中的move()
是否不正确?我得到的错误在代码下面:
#include<memory>
#include<iostream>
struct node{
int data;
std::unique_ptr<node> next;
};
void print(std::unique_ptr<node>head){
while (head)
std::cout << head->data<<std::endl;
}
std::unique_ptr<node> insertNode(std::unique_ptr<node>head, int value){
node newNode;
newNode.data = value;
//head is empty
if (!head){
return std::make_unique<node>(newNode);
}
else{
//head points to an existing list
newNode.next = move(head->next);
return std::make_unique<node>(newNode);
}
}
auto main() -> int
{
//std::unique_ptr<node>head;
//for (int i = 1; i < 10; i++){
// //head = insertNode(head, i);
//}
}
错误std::unique_ptr>:unique_pr(const std::unique_ptr<_Ty,std::default_delete<_Ty>&)':试图引用已删除的函数
除了其他小问题外,主要问题是这一行:
return std::make_unique<node>(newNode);
您正试图构造一个指向新节点的唯一指针,将newNode
传递给node
的复制构造函数。但是,node
的复制构造函数被删除,因为node
包含不可复制的类型(即std::unique_ptr<node>
)。
您应该传递一个std::move(newNode)
,但这是有问题的,因为您在堆栈上创建了节点,它将在函数的出口处被销毁。
在我看来,使用std::unique_ptr
是个坏主意,因为例如,要打印列表(或插入列表),你需要std::move
、head
(所以你会丢失它)等等。我认为使用std::shared_ptr
会更好。
我也遇到了同样的问题,确实使用了shared_ptr
。
在函数中使用智能指针作为参数会复制指针(而不是它指向的数据),这会导致unique_ptr
重置并删除它以前指向的数据——因此我们会出现"试图引用已删除的函数"错误。如果您使用shared_ptr
,这将简单地增加引用计数,并在超出该函数的范围后取消增量。
上面答案中的评论表明,使用shared_ptr是毫无根据的。这些答案是在C++17标准之前编写的,据我所知,我们应该使用该语言的最新版本,因此shared_ptr
在这里是合适的。
我不知道为什么我们必须在任何情况下向用户公开节点类型。正如我的一位导师所说,C++的全部功能是写更多的代码,以便以后写更少的代码。
我们希望封装所有内容,不给用户留下节点的头或尾(双关语)。非常简单的界面看起来像:
struct list
{
private:
struct node {
int data;
std::unique_ptr<node> next;
node(int data) : data{data}, next{nullptr} {}
};
std::unique_ptr<node> head;
public:
list() : head{nullptr} {};
void push(int data);
int pop();
~list(); // do we need this?
};
该实现实现实现了Ben Voigt所提到的一些功能:
void list::push(int data)
{
auto temp{std::make_unique<node>(data)};
if(head)
{
temp->next = std::move(head);
head = std::move(temp);
} else
{
head = std::move(temp);
}
}
int list::pop()
{
if(head == nullptr) {
return 0; /* Return some default. */
/* Or do unthinkable things to user. Throw things at him or throw exception. */
}
auto temp = std::move(head);
head = std::move(temp->next);
return temp->data;
}
实际上,我们需要一个析构函数,若列表真的很大,那个么它就不会是递归的。我们的堆栈可能会爆炸,因为节点的析构函数会调用unique_ptr的析构因子,然后会调用托管节点的析构函数,后者会调用unique _ptr的destructor。。。令人作呕。
void list::clear() { while(head) head = std::move(head->next); }
list::~list() { clear(); }
在此之后,默认的析构函数将只为head
ping unique_ptr
析构函数一次,而不进行递归迭代。
如果我们想在不弹出节点的情况下遍历列表,我们会在一些设计用于处理该任务的方法中使用get()
。
Node *head = list.head.get();
/* ... */
head = head->next.get();
get()
在不中断管理的情况下返回原始指针。
这个例子怎么样,除了示例代码,他还提到了一些原则:
当你需要";分配"——使用std::move,当您只需要遍历时,使用get()
- 何时在引用或唯一指针上使用移动语义
- C++优先级队列,按对象的唯一指针的特定方法升序排列
- 如何使用Visual Studio 2017在C++中为参数化对象数组使用唯一指针
- 如何更改唯一指针向量的可见性
- 共享指针和具有自定义删除程序的唯一指针之间的语法差异背后的任何原因
- C++尝试深度复制唯一指针时出现内存访问冲突
- 使用 RTTI 克隆唯一指针的向量
- 为什么我无法创建唯一指针
- 如何将唯一指针的 std::vector 转换为原始指针的 std::span?
- 将唯一指针的指针传递给采用双指针的函数
- 在什么情况下,需要共享智能指针而无法使用唯一指针?
- C++唯一指针的向量
- 对带有唯一指针的 std::thread 使用类成员函数时出现编译错误
- 指向基类的唯一指针
- 添加要映射的对象的唯一指针
- 智能指针(唯一指针)和引用
- 唯一指针是否在堆或堆栈上分配内存?
- 尝试设置唯一指针布尔数组的值时BAD_ACCESS错误
- 使用唯一指针调用函数会使我的程序崩溃
- 将唯一指针插入std::映射