【问题标题】:C++ pattern for pointer deletion?用于指针删除的 C++ 模式?
【发布时间】:2021-06-14 22:27:11
【问题描述】:

我想知道是否存在删除指针的模式。更具体地说,当您需要为数据调用某种中间函数时。这是我的想法的一个例子:

int main() {
    // some code here

    char* return_of_function1 = function1(int_array);
    int return_of_function2 = function2(return_of_function1);
    delete[] return_of_function1;

    // some code here
} 

char* function1(int* int_array) {
    // some code here
}

int function2(char* char_array) {
    // some code here
}
int main() {
    // some code here

    int return_of_function2 = function2(int_array);

    // some code here
}

char* function1(int* int_array) {
    // some code here
}

int function2(int* int_array) {
    // some code here
    return function2(function1(int_array), true);
}

int function2(char* char_array, bool delete_array) {
    // some code here

    if(delete_array) {
        delete[] char_array;
    }

    return /* return value */;
}

动机是避免对集合属性数据的中间调用。同样,我只是想问一下这是否常用,或者是否是一个好主意。

非常感谢。

【问题讨论】:

  • 如果你想要一个模式,RAII 是一个不错的选择。它需要将您的指针包装在一个类中,以便它可以自动为您分配和删除。但是,这很常见,std::unique_ptr 存在。不过,我仍然需要一些时间来阅读 RAII。
  • 这些都不是常用的,也不是一个好主意。使用智能指针。
  • 如果您想要一个运行时大小的数组,std::vector 是您首选的 RAII 容器。它会为你管理内存。
  • 最好的模式是不要使用 new 或 delete ,除非你被学术要求强迫。而是使用标准库中的容器之一或智能指针。

标签: c++ c++11 pointers gcc memory


【解决方案1】:

一般做法是按照您使用原始指针的方式远离原始指针。如果你的 char * 真的是一个字符串,那么例如使用 std::string。

RAII 代表 Resource Acquisition is Initialization。重要的是你用一个对象包装你的资源,然后让这个对象超出范围。它会因超出范围而被破坏,而析构函数是您唯一需要担心破坏数据的地方。如果你真的要使用 char * 并且它不是真正的字符串,因此你应该使用字符串,它可能看起来像这样:

class CharArray {
public:
     CharArray(whatever args you need);
     virtual ~CharArray() { if (ptr) delete[] ptr; }
private:
     char * ptr = nullptr;
};

如果 CharArray 的任何方法实际上可以更改 ptr,那么您需要确保首先小心地释放旧内容。

您还需要确保您拥有完整的移动构造函数/运算符等,以便您可以安全地返回它。

另一种选择是智能指针。请参阅 std::shared_ptrstd::unique_ptr。这些家伙很棒。他们通过引用计数为您处理所有这些。

【讨论】:

  • std::unique_ptr 没有引用计数。此外,如果他们有不是字符串的 char 数据,std::vector<char>std::string 的合适替代品。
  • 1) if (ptr) 在析构函数中是没用的。无论如何,当ptr 为nullptr 时,delete 是一个 noop。 2) CharArray 的副本呢?如果制作了此类实例的任何副本,它不会导致 UB 吗?
  • @AlgirdasPreidžius 我只是在演示基本思想,而不是提供 200 行的完整实现。
  • @AlgirdasPreidžius 关于“2)”有一段 “您还需要确保您拥有完整的移动构造函数/运算符等,因此您可以安全地返回它。 " 解决了这个问题,尽管与 3/5/0 规则的链接不会受到伤害。
  • @JosephLarson "我只是在演示基本思想,而不是提供 200 行的完整实现。" 1) 代码中不需要的构造 (if (ptr)) 增加示例的长度,而不是减少它。 2)我并没有要求完全实施。我只是看到人们看到代码示例、复制它并惊讶于它在某些条件下失败的危险,就像被复制一样简单。
猜你喜欢
  • 2010-09-08
  • 1970-01-01
  • 2018-05-14
  • 1970-01-01
  • 1970-01-01
  • 2021-07-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多