c++ - C++中的指针容器
问题描述
我正在阅读“使用 qt 在 c++ 中介绍设计模式”一书。在第 6 章中(参见书籍链接https://www.ics.com/designpatterns/book/containersofpointers.html),作者正在尝试编写一个继承自 QList 的库类。在addRefItem
定义函数的示例 6.35 中。作者有非常奇怪的(至少对我来说)处理指针的方式。
void Library::addRefItem(RefItem*& refitem) {
在这里,作者使用了指针引用*&,他解释说“这样删除后的空赋值是可能的”。我认为这与最后两行有关。
QString isbn(refitem->getISBN());
RefItem* oldItem(findRefItem(isbn));
if(oldItem==0)
append(refitem);
else {
qDebug() << isbn << " Already in list:\n"
<< oldItem->toString()
<< "\nIncreasing number of copies "
<< "and deleting new pointer." ;
int newNum(oldItem->getNumberOfCopies() + refitem->getNumberOfCopies());
oldItem->setNumberOfCopies(newNum);
delete refitem;
refitem = 0;
}
}
我不明白最后两行是做什么的。为什么refitem
需要删除。函数返回后它无论如何都会被破坏,对吧?然后为什么refitem
需要分配为0。
在removeRefItem
函数中,也有类似的一行delete ref
,见下文。谁能帮我理解所有这些?非常感谢。
int Library::removeRefItem(QString isbn) {
RefItem* ref(findRefItem(isbn));
int numCopies(-1);
if(ref) {
numCopies = ref->getNumberOfCopies() - 1;
if(numCopies== 0) {
removeAll(ref);
delete ref;
}
else
ref->setNumberOfCopies(numCopies);
}
return numCopies;
}
解决方案
你觉得这很奇怪。你应该。如果可以避免的话,不要做这样的事情。一般来说,避免像瘟疫一样的手动内存管理。看看你是否可以用s替换它std::shared_ptr
。这将需要一些工作,但结果会更加强大。
函数返回后它无论如何都会被破坏,对吧?
不RefItem*& refitem
提供对指针的引用,但是因为提供了引用,所以您知道传递给函数的任何对象都没有作用域,addRefItem
因为它来自其他地方。如果它要被自动销毁,它将在其他地方被销毁。
我不明白最后两行是做什么的。为什么需要删除“refitem”。函数返回后它无论如何都会被破坏,对吧?然后为什么需要将“refitem”分配为0。
您不知道对象refitem
指向的对象是如何分配的,无论是自动分配还是动态分配,因此您不知道它何时会超出范围,但不会在addRefItem
. refitem
特别是 的使用delete refitem;
表明它是动态分配的。如果不是,程序注定会出现Undefined Behavior。
为什么ref
's 的对象被破坏了?我们已经有一个了。为什么有两个?此代码将相同的 s 聚合RefItem
为单个RefItem
,维护该对象被复制的次数的计数,该计数存储在列表中。现在冗余的对象被销毁。这使得RefItem
引用计数对象。
代码块 1 显示,如果项目已经在列表中,则提供的对象将被销毁和释放,delete refitem;
并且指向它的指针被清空,refitem = 0;
以便更容易检测到该对象不再存在。如果此函数的调用者尝试使用空指针,则会发生未定义行为,但绝大多数系统,我在过去 20 年左右所做的一切工作,都会将使用检测为无效并崩溃程序。
这个我不太明白。与其将指针清空,不如将指针更新为指向列表中吸收并替换传入的指针的项。更完整的示例可以更好地解释这种选择。
顺便说一句,不要使用0
空指针。与(C++11 或更高版本)或(C++11 之前的)0
相比,更难辨别代码的用途。 有很多含义。有一个。nullptr
NULL
0
nullptr
在 removeRefItem 函数中,也有类似的一行,“delete ref”,见下文。谁能帮我理解所有这些?非常感谢。
在第二个代码示例中,如果未完成副本的数量(引用计数)减少到 0,则removeRefItem
销毁并释放。ref
附录:std::shared_ptr
当此代码可以轻松实现时,为什么在此答案的序言中推荐 a std::unique_ptr
?因为这段代码似乎正在实现一个引用计数指针。我可能是大错特错,在这种情况下std::unique_ptr
是要走的路。只需unique_ptr
从容器中删除它,让它退出范围,让系统为您处理破坏。如果这是一个用于从列表中检出和检入指向同一对象的指针的系统,std::shared_ptr
那么它会为您完成所有这些工作,并且做得很好而且安全。为什么要std::unique_ptr
在工作中使用工具包?
推荐阅读
- swiftui - 在swiftui中使用组合从服务器获取更多数据时如何追加
- arrays - 计算一个数字在随机数组中出现的次数
- c - 不使用 struct 在 C 中显示所有数据
- c++ - 为什么 Visual Studio 试图从 Team Fortress 2 加载 SDL2?
- lisp - lisp 中的递归跟踪......可以使用一些建议
- machine-learning - 在随机森林回归器中执行修剪的正确方法是什么?
- visual-studio-code - Arduino vscode:标识符“sprintf”未定义
- prolog - source_sink `library(matrix)' 不存在
- input - 变音符号和上标的简单输入
- php - Laravel - 如何汇总子数据并将其传递给父@foreach