c++ - C++中的指针容器

标签 c++ qt pointers containers

我正在阅读《使用 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_ptrs .这需要一些工作,但结果会更加稳健。

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/

相关文章:

c++ - 为什么 INSERT 和 DELETE 会搞砸 QTableView(Qt、C++、sqlite)?

c - 在嵌入式中取消引用 NULL 指针

c++ - shared_ptr、vector、emplace_back 和外部使用指针

c++ - 对于给定的数字 N,我如何找到 x,(x 和 x 的因子数)= N 的 S.T 乘积?

c++ - 数组中的重复数字

multithreading - 为什么信号/槽不适用于多线程?

c++ - 指向第一个元素的指针的地址

c++ - Bison C++ : error expected initializer before ‘*’ token

c++ - "import"从基类定义一个函数来实现抽象接口(interface)(C++中的多重继承)

qt - QSettings INI 文件 : value containing semicolon