C++ 中的指针容器
container of pointers in c++
我正在阅读"使用 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;
}
你觉得这很奇怪。你应该。如果可以避免,不要做这样的事情。通常,请避免像瘟疫一样手动进行内存管理。看看是否可以将其替换为std::shared_ptr
s。这将需要一些工作,但结果会更加强大。
无论如何,函数返回后它都会被销毁,对吧?
不。RefItem*& refitem
提供对指针的引用,但由于提供了引用,因此您知道传递到函数的任何对象都不在addRefItem
范围内,因为它来自其他位置。如果要自动销毁,它将在其他地方销毁。
我不明白最后两行是做什么的。为什么需要删除"refitem"。无论如何,函数返回后它都会被销毁,对吧?然后为什么需要将"refitem"分配为 0。
你不知道refitem
点的对象是如何分配的,它是自动分配的还是动态分配的,所以你不知道它什么时候会超出范围,但它不会在addRefItem
中自动销毁。refitem
的使用,特别是delete refitem;
,表明它是动态分配的。如果不是,该程序注定要进行未定义的行为。
为什么ref
的物体会被销毁?我们已经有一个了。为什么有两个?此代码将相同的RefItem
聚合到单个RefItem
中,维护此对象被复制的次数的计数,该次数存储在列表中。现在冗余的对象将被销毁。这使RefItem
成为引用计数的对象。
代码块 1 显示,如果该项已在列表中,则提供的对象将被销毁并使用delete refitem;
释放,指向它的指针将空,并带有refitem = 0;
,以便更容易检测到该对象不再存在。如果此函数的调用者尝试使用空指针,则会发生未定义行为,但绝大多数系统,我在过去 20 年左右所做的一切,都会将用法检测为无效并导致程序崩溃。
这个我不太明白。我不会将指针清空,而是更新指针以指向列表中吸收并替换传入的指针的项目。一个更完整的例子可以更好地解释这种选择。
顺便说一句,不要使用0
来清空指针。与nullptr
(C++11 或更高版本)或NULL
(C++11 之前)相比,很难辨别0
的代码在做什么。0
有很多含义。nullptr
有一个。
在 removeRefItem 函数中,也有类似的行,"delete ref",见下文。谁能帮我理解所有这些?非常感谢。
在第二个代码示例中,如果未完成副本数(引用计数)减少到 0,removeRefItem
销毁并释放ref
。
附录:当此代码可以使用std::unique_ptr
轻松实现时,为什么要建议在此答案的序言中std::shared_ptr
?因为此代码似乎正在实现引用计数指针。我可能大错特错,在这种情况下std::unique_ptr
就是要走的路。只需从容器中取出unique_ptr
,让它超出范围,让系统为您处理销毁。如果这是一个用于从列表中检出和插入指向同一对象的指针的系统,std::shared_ptr
会为您完成所有这些操作,并且做得又好又安全。为什么要让std::unique_ptr
做这项工作?
作者使用指针引用 *&,他解释说"以便删除后可以进行空赋值"。 我假设这与最后两行有关。
这意味着,如果您只是将其作为指针传递,您仍然可以执行refitem = 0;
但是当函数返回时,该值不会结转。因此,作为指针引用传递可以实现这一点。
我不明白最后两行是做什么的。为什么需要删除"refitem"。
refItem
是一个指针(根据设计指向分配的内存),必须在某处删除。查看代码,作者正在分配此函数删除它的责任。
关键问题是作者希望确保当函数返回addRefItem()
,如果成功删除refitem
的值应设置为 null。如果指针没有与引用一起传递,这是不可能的。
- 1d 智能指针不适用于语法 (*)++
- 在C#中处理C++指针而不使用unsafe的最佳方法
- 为什么使用 "this" 指针调用派生成员函数?
- 函数向量_指针有不同的原型,我可以构建一个吗
- 使用指针从C++中的数组中获取最大值
- 助记符和指向成员语法的指针
- 嵌入方指针压缩已禁用
- 数组的指针从不分段故障
- C++ 指针的内存地址和指向数组的内存地址如何相同?
- 何时在引用或唯一指针上使用移动语义
- QMetaObject invokeMethod的基于函数指针的语法
- 如何从 std::atomic 中提取指针 T<T>?
- 如何在 C# 中映射双 C 结构指针?
- C++将浮点指针值舍入为小数位数
- 为什么++(*p)更改指针值
- 调整大小后指向元素值的指针unordered_map有效?
- 正在将指针转换为范围
- 使用指向成员的指针将成员函数作为参数传递
- 将OpenCV C++重写为EmguCV C#-如何使用指针
- C++-试图将函数指针推回到另一个CPP文件中的矢量时出错