我试图在我的打印函数中创建一个临时变量'p'。我得到一个编译器错误和两个警告,我不知道如何处理。
一旦我有了print函数的句柄,大多数函数就会被遗漏,以便稍后填充。
我还重新定义了cout<<&n来打印链表的值。
unique_ptr.h||In instantiation of 'typename std::_MakeUniq<_Tp>::__single_object std::make_unique(_Args&& ...) [with _Tp = Node; _Args = {const std::unique_ptr<Node, std::default_delete<Node> >*}; typename std::_MakeUniq<_Tp>::__single_object = std::unique_ptr<Node>]':|
Deque.cpp|46|required from here|
/usr/include/c++/6/bits/unique_ptr.h|787|error: invalid conversion from 'const std::unique_ptr<Node>*' to 'int' [-fpermissive]|
Node.h|15|note: initializing argument 1 of 'Node::Node(int)'|
| | = = =构建失败:1错误(s), 2警告(s)(0分钟(s), 0秒(s)) = = = |
Main.cpp
#include <iostream>
#include "Node.h"
#include "Deque.cpp"
using std::cout;
using std::endl;
std::ostream& operator<<(std::ostream& out, const Node& n) {
return out << &n << ": " << n.val << " -> " << n.next.get();
}
int main()
{
return 0;
}
Node.h
#ifndef NODE_H
#define NODE_H
#include <iostream>
#include <memory>
class Node {
public:
Node(const Node& n) : val{n.val}, next{}
{
}
Node(int v, std::unique_ptr<Node> n) : val{v}, next{move(n)}
{
}
Node(int v) : val{v}
{
}
private:
int val = 0;
std::unique_ptr<Node> next = nullptr;
friend class Deque;
friend std::ostream& operator<<(std::ostream&, const Node&);
};
#endif
Deque.h
#include <memory>
class Deque{
public:
Deque() = default;
Deque(const Deque&);
~Deque(); //must use constant space
Deque& operator=(const Deque&); //we can use assignment in this assignement lols.
void print_queue(const std::string& label) const; //prints all nodes in queue,
//together with pointers to head and tail and also size of queue.
//routine calls the node output function - not tested
private:
std::unique_ptr<Node> head;
std::unique_ptr<Node> tail;
friend Node;
};
Deque.cpp
#include "Deque.h"
#include <memory>
using std::cout;
using std::endl;
void Deque::print_queue( const std::string& label) const
{
std::unique_ptr<Node> p = std::make_unique<Node>(&head);
cout<< "This is the linked list: " << endl;
while ( p != NULL)
{
cout<< &head;
}
}
看看你的代码,我认为你应该多读两件事。首先是引用和c++中&
操作符的多重含义。
当你有这样一个函数:
void f(const Type& param);
表示param
是对const Type
的引用。本例中的&
将param
声明为引用。如果你想调用这个方法,你可以这样做:
Type value;
f(value);
注意,参数value
是按原样传递的,没有任何其他限定符。如果您尝试像这样调用函数:
f(&value);
那么&
意味着address of
和&value
不是引用,它是一个指针,这要求函数看起来像:
void f(Type *param);
这解释了当你写这个时你得到的错误:
std::unique_ptr<Node> p = std::make_unique<Node>(&head);
这里head
是std::unique_ptr<Node>
,所以&head
是指向unique_ptr<Node>
的指针。这就是错误信息告诉你的:
invalid conversion from 'const std::unique_ptr<Node>*' to 'int'
它试图调用Node
构造函数,接受int
参数,无法将指针从unique_ptr
转换为int
。
您应该更多地了解的第二件事是unique_ptr
本身。简而言之,unique_ptr
是一个单所有权智能指针,它不能被复制,你不能让unique-ptr
管理同一个对象。这就是为什么你不能在你的代码中这样做:
std::unique_ptr<Node> p = head;
在这种情况下,错误信息基本上告诉你没有unique_ptr
的复制构造函数。
因为你不能复制unique_ptr
s,所以用你写的方式遍历一个链表就不能像你平时做作业那样做了。在实现列表上的其他操作(如插入或删除节点)时,您还必须更加仔细地考虑。
但是让我们坚持遍历列表。你不能复制unique_ptr
s,所以你必须使用引用或原始指针来访问它们。
这个方法也不直接,因为引用在定义后不能"重新分配"。所以你可以尝试递归地做,例如:
void printNodeAndGoNext(const std::unique_ptr<Node> &node)
{
if (node)
{
std::cout << node->value;
printAndGoNext(node->next);
}
}
void print()
{
printNodeAndGoNext(head);
}
这只使用对unique_ptr
s的引用,它不需要创建节点的任何副本。但和递归函数一样,它不能缩放。不要这样做。
您可以使用原始的非拥有指针指向unique_ptr
本身或它们正在管理的底层节点。
第一个版本是这样的:
void print()
{
const std::unique_ptr<Node> *node = &head;
while(node)
{
std::cout << (*node)->value;
node = &((*node)->next);
}
}
注意*
s和&
s以及您得到的实际数据类型。
第二个版本,使用原始指针指向实际节点:
void print()
{
const Node *node = head.get();
while (node)
{
std::cout << node->value;
node = node->next.get();
}
}
在所有这些之间,最后一个版本将是首选的。使用原始的非拥有指针指向由拥有unique_ptr
s管理的对象是完全可以的,如果你稍微小心的话。
免责声明
上面的代码片段只是为了说明要点,你必须适应这些想法,并根据你的情况实际编写代码。
未来面临的问题
我已经提到了其中的一些。您必须使用unique_ptr
的独特属性来实现标准的列表操作,如插入和删除。
另一个需要考虑(和修复)的方面又与递归有关。更具体地说,当你有一个这样的列表,它有更多的节点(数千个节点,数万个,数百万个等等),你想要摧毁它会发生什么?