我正在阅读《使用 qt 的 C++ 中的设计模式简介》一书。在第 6 章中,(参见本书链接 https://www.ics.com/designpatterns/book/containersofpointers.html),作者试图编写一个继承自 QList 的库类。在示例 6.35 中定义了 addRefItem
函数。作者有非常奇怪的(至少对我而言)处理指针的方式。
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;
}
最佳答案
你觉得这很奇怪。你应该。如果可以避免,请不要做这样的事情。一般来说,Avoid manual memory management就像瘟疫一样。看看能不能replace this with std::shared_ptr
s .这需要一些工作,但结果会更加稳健。
It will be destructed anyway after the function return, right?
没有。 RefItem*& refitem
提供对指针的引用,但由于提供了引用,您知道传递给函数的任何对象都不在 addRefItem
范围内,因为它来自别处。如果要自动销毁,它将在其他地方销毁。
I don't understand what the last two lines do. Why "refitem" need to be deleted. It will be destructed anyway after the function return, right? and then why "refitem" need to be assigned to be 0.
你不知道refitem
指向的对象是怎么分配的,是不是automatically or dynamically allocated所以你不知道它什么时候会超出范围,但它不会在 addRefItem
中自动销毁。 refitem
的用法,特别是 delete refitem;
,表明它是动态分配的。如果不是,程序注定要Undefined Behaviour。 .
为什么 ref
的对象被销毁了?我们已经有了一个。为什么有两个?此代码将相同的 RefItem
聚合到单个 RefItem
中,维护此对象被复制次数的计数,该计数存储在列表中。现在冗余的对象被销毁。这使得 RefItem
成为 reference-counted object .
代码块 1 显示,如果该项目已经在列表中,则使用 delete refitem;
销毁并释放所提供的对象,并使用 refitem = 0; 将指向它的指针清空;
以便更容易检测到该对象已不复存在。如果此函数的调用者尝试使用空指针,则会发生未定义的行为,但绝大多数系统,我在过去 20 年左右的时间里所做的一切,都会检测到该用法无效并崩溃程序。
这个我不是很明白。我不会使指针为空,而是更新指针以指向吸收并替换传入指针的列表中的项目。一个更完整的示例可以更好地解释这个选择。
顺便说一句,不要使用0
来使指针为空。与 nullptr
(C++11 或更新版本)或 NULL
相比,使用 0
更难辨别代码的用途(C++11 之前)。 0
有很多含义。 nullptr
有一个。
In the removeRefItem function, there is also a similar line, "delete ref", see below. Can anyone help me understand all of these? A lot of thanks.
在第二个代码示例中,removeRefItem
销毁并释放 ref
,如果未完成的拷贝数(引用计数)减少到 0。
附录:当这段代码可以很容易地用 std::unique_ptr
实现时,为什么要在这个答案的序言中推荐 std::shared_ptr
?因为这段代码似乎是在实现一个引用计数指针。我可能完全错了,在那种情况下 std::unique_ptr
是正确的选择。只需从容器中删除 unique_ptr
并让它退出范围,让系统为您处理销毁。如果这是一个用于从列表中 check out 和检入指向同一对象的指针的系统,std::shared_ptr
会为您完成所有这些工作,而且做得很好而且安全。为什么 kit-bash 一个 std::unique_ptr
来完成这项工作?
关于c++ - C++中的指针容器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56623925/