C++中动态分配的单向链表的赋值运算符 (MS Visual Studio 2015)
Assignment Operator for singly linked list with dynamic allocation in C++ (MS Visual Studio 2015)
两个类,一个用于节点,一个用于单向链表。
// node class
template <typename T>
class Element{
private:
Element *next_ = nullptr;
string name_ = "";
T color_ = T();
public:
Element()=default;
Element(string name, T d) : next_(nullptr), name_(name), color_(d){};
friend ostream& operator<<(ostream& out, Element& n){
out << n.name_ << ":" << n.color_;
return out;
}
friend class PAL<T>;
};
/* "This is a singly linked list of Elements that, taken in order,
constitute the Painter's ALgorithm." */
template<typename T>
class PAL{
private:
Element<T> *back_ = nullptr;
Element<T> *front_ = nullptr;
void print_list(ostream& out);
public:
PAL()=default;
PAL(Element<T> n) : back_(&n), front_(&n) {};
PAL(string n, T d);
PAL(const PAL&);
~PAL();
PAL& operator=(PAL);
void add(Element<T> &n);
void add(string name, T dat);
pair<Element<T>*, Element<T>*> find(string name);
pair<Element<T>*, Element<T>*> find(Element<T> &n);
void move_forward1(Element<T> &n);
void move_to_front(Element<T> &n);
void move_back1(Element<T> &n);
void move_to_back(Element<T> &n);
friend ostream& operator<<(ostream& out, PAL<T>& sl){
sl.print_list(out);
return out;
}
现在对于赋值运算符,我尝试了两件事。
template<typename T>
PAL<T> & PAL<T>::operator=(PAL p)
{
front_ = p.front_;
back_ = p.back_;
return *this;
}
以及使用 std::swap 的变体。 两者都编译,但给出运行时错误。
当我使用 swap 时,我最终会出现一个错误,我认为它说内存不足?
表达式:"(_Ptr_user & (_BIG_ALLOCATION_ALIGNMENT -1)) == 0" &&&0
如果我使用第一个,没有交换,就会发生奇怪的狗屎。我调试并观察了"this"和"p",因为它逐步执行了函数,它运行良好,直到最后,最后一个括号意味着什么,突然"p"和"this"不仅更改为nullptrs,而且更改为0xdddddd(我猜d的数量)。所以它有各种各样的问题。
我想知道为什么会发生这些事情,但如果没有别的,我需要知道我应该做什么!
非常感谢。
编辑:该功能现在如下。
template<typename T>
PAL<T> & PAL<T>::operator=(const PAL &p)
{
Element<T> *new_front = nullptr, *new_back = nullptr;
Element<T> *address = p.back_;
while (address != nullptr) {
/* the add method in this loop will end up taking
care of front_ and back_ too */
add(address->name_, address->color_);
pair<Element<T>*, Element<T>*> found = find(address->name_);
if (new_front == nullptr) {
new_front = found.first;
}
new_back = found.first;
//move_to_front(*found.first);
address = address->next_;
}
Element<T> *old = p.back_;
while (old) {
Element<T> *last = old;
old = old->next_;
delete last;
}
front_ = new_front;
back_ = new_back;
return *this;
}
请注意,back_表示列表中的"第一个"项(没有任何内容指向它),front_表示最后一个,它不指向任何内容。
复制赋值操作员的工作不仅仅是复制指针;默认编译器生成可以为您做到这一点。
此运算符的工作是将另一个对象的内容复制到一个完全独立的对象中。 这意味着将每个Element<T>
对象从另一个对象复制到此对象中。 这也意味着您必须处理销毁当前对象包含的任何节点。
只需像您所做的那样复制指针,就意味着对一个PAL<T>
的更改可能会反映在另一个中。 如果头部或尾部发生变化,则只有一个PAL<T>
会发生此更改。
更糟糕的是,如果您复制分配一个PAL<T>
而不是另一个,您现在有两个PAL<T>
对象认为自己拥有它们包含Element<T>
对象。 然后,当两者都销毁时,它们将各自尝试删除这些对象。 这会导致双重释放,从而导致未定义的行为。
首先,更改运算符以引用常量而不是副本。
然后,您将要使用的常规模式如下所示:
template<typename T>
PAL<T> & PAL<T>::operator=(const PAL &p)
{
// Store the old list here, which we will deallocate at the end. This
// step is necessary to do first in case some code copy-assigns an
// instance to itself; since in that case it is copying its own data,
// we can't deallocate it yet or we will just lose the data completely.
Element<T> *old_back = back_;
// Reset this instance.
front_ = nullptr;
back_ = nullptr;
// Duplicate the elements of p, storing them in this object.
// You will have to make sure the next_ fields of the new elements point
// into the duplicated chain, not the original!
//
// Left as an exercise for you to implement.
// Deallocate and free the nodes that were contained in this object.
while (old_back) {
Element<T> *last = old_back;
old_back = old_back->next;
delete last;
}
return *this;
}
我猜你的复制构造函数也不会做这种复制。 如果没有,那么你可以用这个运算符来实现它,以尽量减少代码重复:
template<typename T>
PAL<T>::PAL(const PAL &p) : front_(nullptr), back_(nullptr) {
*this = p;
}
- 如何在MS Visual Studio 2019中运行QT UI
- MS Visual Studio 解决方案结合了非托管C++项目和 C# 项目
- 从现有源创建 MS Visual C++ DLL 项目
- 带有unique_ptr的通用单链表,MS visual studio C++中存在未知错误
- Python:在Windows上选择C++编译器 - MS Visual Studio到Mingw-w64.(PySta
- 在 Ubuntu 12.04 上运行,一个在 Windows 上的 MS Visual Studio 中用 c++11
- C++中动态分配的单向链表的赋值运算符 (MS Visual Studio 2015)
- MS Visual C 释放和调试构建之间的不同行为的可能原因
- 在 Windows 7 下的 Visual Studio 2015 上缺少 Api-ms-win-core-errorh
- stdlib.h's random() on MS Visual Studio 2008
- C++ File - MS Visual Studio
- MS Visual Studio 2012和OpenCV 2.4.5-未显示图像
- std::reference_wrapper on MS Visual Studio 2013
- 如何使 MS-Visual C++应用程序最大化
- 在MS Visual Studio 2010上使用带有Cuda互操作的OpenGL缓冲区时出现异常错误
- 在MS Visual Studio 2010监视窗口中评估模板函数
- 是否将资源(声音文件)添加到exe?[MS Visual Studio 2012]
- MS Visual Studios链接错误.2010年和2013年
- 哪些组件与MS Visual Studio 2012/2013一起安装是不必要的
- strcpy_s是C++标准的一部分吗?或者只是MS Visual C++的一部分