我是不是正确删除了指向对象的指针向量?

Posted

技术标签:

【中文标题】我是不是正确删除了指向对象的指针向量?【英文标题】:Am I deleting my vector of pointers to objects correctly?我是否正确删除了指向对象的指针向量? 【发布时间】:2018-02-27 10:47:04 【问题描述】:

我目前正在开发一个程序,我从各种 CAN 信号中读取信息并将它们存储在 3 个不同的向量中。 对于每个信号,都会创建一个指向对象的新指针并将其存储在两个向量中。 我的问题是,当我删除向量时,当我删除一个向量中指向对象的指针并清除另一个向量时是否足够。

这是我的代码:

将向量声明为迭代器:

std::vector <CAN_Signal*> can_signals; ///< Stores all CAN signals, found in the csv file
std::vector <CAN_Signal*> can_signals_rx; ///< Stores only the Rx CAN signals, found in the csv file
std::vector <CAN_Signal*> can_signals_tx; ///< Stores only the Tx CAN signals, found in the csv file
std::vector <CAN_Signal*>::iterator signal_iterator; ///< Iterator for iterating through the varoius vectors

填充向量:

for (unsigned int i = 0; i < m_number_of_lines; ++i)

    string s = csv_file.get_line(i);

    CAN_Signal* can_signal = new CAN_Signal(s, i);

    if (can_signal->read_line() == false)
        return false;

    can_signal->generate_data();

    can_signals.push_back(can_signal);

    if (get_first_character(can_signal->get_PDOName()) == 'R')
    
        can_signals_rx.push_back(can_signal);
    
    else if (get_first_character(can_signal->get_PDOName()) == 'T')
    
        can_signals_tx.push_back(can_signal);
    
    else
    
        cout << "Error! Unable to detect whether signal direction is Rx or Tx!" << endl;
        return false;
       

删除向量:

File_Output::~File_Output()

    for (signal_iterator = can_signals.begin(); signal_iterator != can_signals.end(); ++signal_iterator)
    
        delete (*signal_iterator);
    
can_signals.clear();

//for (signal_iterator = can_signals_rx.begin(); signal_iterator != can_signals_rx.end(); ++signal_iterator)
//
//  delete (*signal_iterator);
//
can_signals_rx.clear();

//for (signal_iterator = can_signals_tx.begin(); signal_iterator != can_signals_tx.end(); ++signal_iterator)
//
//  delete (*signal_iterator);
//
can_signals_tx.clear();

cout << "Destructor File_Output!" << endl;

当我取消注释注释的 for 循环并运行程序时,它会在调用析构函数时崩溃。 所以我的猜测是,这是正确的做法,因为指针已经被删除,只需清除剩余的两个向量就足够了。

但我不太确定,也很想听听专家对此的意见。

非常感谢。

【问题讨论】:

改成std::vector&lt;std::unique_ptr&lt;CAN_Signal&gt;&gt; 就可以早点下班了。 测试似乎支持newdelete 的调用次数应该相同的规则。如果您遵循 Bathsheba 的建议并改用 make_unique,您可以将数字降至零 - 这是非常相等的。 @Bathsheba 你介意发布一个如何使用它的例子吗?我无法弄清楚这是如何工作的。 什么,even after reading the documentation and examples? @Bathsheba 为什么不简单地std::vector &lt;CAN_Signal&gt; 【参考方案1】:

当我删除向量时,当我删除指向一个向量中对象的指针并清除另一个向量时是否足够。

由于其他向量中的指针是副本,因此仅在一个向量中删除它们就足够了,而且删除这些副本实际上会产生未定义的行为。你永远不希望你的程序有未定义的行为。

假设向量是File_Output 的成员,清除File_Output 的析构函数中的任何向量似乎是不必要的。这是因为无论如何成员都将被销毁。

我是否正确删除了指向对象的指针向量?

假设您没有复制在其他地方删除的指针:是的,这是删除它们的正确方法。


您的代码存在内存泄漏:

CAN_Signal* can_signal = new CAN_Signal(s, i);
if (can_signal->read_line() == false)
    return false;

如果该条件为真,那么新分配的CAN_Signal 将被泄露,因为函数返回时指针既不会被删除也不会存储在任何地方。


你的代码不是异常安全的:如果这些行中的任何一行抛出,那么指针就会泄露。

if (can_signal->read_line() == false)
    return false;
can_signal->generate_data();
can_signals.push_back(can_signal);

目前还不清楚,为什么要首先使用显式内存管理。除非有原因,否则我建议您不要这样做,而是使用std::vector &lt;CAN_Signal&gt; can_signals。这将解决您的内存泄漏和异常安全问题,消除实现自定义析构函数的需要,并使File_Output 的复制/移动构造函数/赋值的实现更简单。

请注意,如果您这样做,您必须为can_signals 的元素分配内存reserve 以防止重新分配,因为其他向量中的指针将在重新分配时失效。作为副作用,这会使程序稍微快一些。

【讨论】:

我已将其更改为 std::vector ,它似乎工作得很好。现在我只是清除析构函数中的向量,这应该足够了吧? (can_signals.clear()) @Burchato 检查我刚刚在编辑中添加的最后一段。考虑使用无效指针具有未定义的行为,并且“工作得很好”是一种可能的未定义行为。不,如果它们是成员,则不需要清除向量。您可以使用隐式析构函数。

以上是关于我是不是正确删除了指向对象的指针向量?的主要内容,如果未能解决你的问题,请参考以下文章

从向量中正确删除指向类的指针

C++ OOP,输出对象指针向量时的空白控制台,不确定填充向量是不是正确

当向量在内部类中时,如何删除指向对象的向量指针

C++ - 创建类对象向量时使用删除的正确方法

如何从指向对象的指针向量中删除对象? [复制]

在删除指向动态分配对象的指针向量中的元素之前,我需要做啥?