繁体   English   中英

C ++中的双指针引用

[英]double pointer reference in C++

这可能是一个愚蠢的问题,但无论如何我都要问它:

假设您有一个指针: Object* pointer动态分配的对象。

class PointClass
{
 Array<Object*> m_array1;
 Array<Object*> m_array2;

 void Delete1()
 {
     for (int i = 0; i < m_array1.Length; i++)
     {
         delete m_array1[i];
     }
 }

void Delete2()
{
    for (int i = 0; i < m_array2.Length; i++)
    {
        delete m_array2[i];
    }
 }
}

现在,您将指针放在m_array1m_array2

当您尝试删除数组时,在其中一个数组中,您将有一个指向已释放空间的指针,因此您无法再次删除它!

我不能在删除后将指针指定为NULL,因为它不会影响另一个数组中的指针。

你会如何解决它?

最简单的方法是使用引用计数指针,就像boost :: smart_ptrs中可用的那样

否则,您需要将所有者分配给指针 - 您需要决定哪个类负责分配/删除该特定指针。 如果由于某种原因你决定应该是这个类,那么你可以通过在枚举它们之前添加指向集合的所有指针来从数组中删除重复项。

如果你必须以这种方式共享指针,像ref count指针这样的东西可能会很好。

请参阅此网站,其中介绍了各种“智能指针”技术。 智能指针

我的初步答案是:不要这样做。

如果由于某种原因你绝对必须,你可以用智能指针包装它

最好的解决方法是不将同一指针传递给两个数组。 :P如果你真的需要,并且你还需要将这个更改反映到所有其他“相同”指针,指针到指针就可以了。

#include <iostream>
struct Object{};

int main(){
  Object* ptr = new Object;
  Object** ptrptr = &ptr;
  delete *ptrptr;
  *ptrptr = 0;
  // both print 0
  std::cout << *ptrptr << std::endl;
  std::cout << ptr << std::endl;
}

关于Ideone
另一种方法是使用引用指针。

int main(){
  Object* ptr = new Object;
  Object*& refptr = ptr;
  delete refptr;
  refptr = 0;
  // both print 0
  std::cout << refptr << std::endl;
  std::cout << ptr << std::endl;
}

但第二种最好的方法可能是重新计算的智能指针。

你会如何解决它?

不将相同的指针存储在两个不同的位置。 这样做会创建数据重复,并混淆所有权语义。 谁拥有pointer的内存? 所有权不明确。

在正常情况下,动态分配的对象应该由分配它的同一模块拥有,并且只有该模块可以直接访问对象或删除内存。 这并不是说其他​​模块无法获取数据。

正如其他人建议使用智能指针来解决您的问题。 如果你必须通过编写自己的代码来解决它,我会让每个删除函数也搜索“其他”数组,删除第一个数组中可以在另一个数组中找到的所有指针。 这是最后一个选项,因为这不是我实现任何方法的第一个解决方案

void Delete2()
{
    for (int i = 0; i < m_array2.Length; i++)
    {
        for (int j = 0; j < m_array1.Length; j++)
        {
            if (m_array2[i] == m_array1[j])
            {
               delete m_array1[j]
               m_array1[j] = NULL;
            }

            delete m_array2[i];
            m_array2[i] = NULL;
    }
}

然后寻找优化它的方法

如果我理解你的问题,你就有相同的(有效的)指针存储在2个不同的数组中。

问题是在array1上删除它之后,你不能在第二个数组中再次执行它。

一种方法是更改​​数组定义以存储指针本身的内存地址,而不是存储已分配内存的地址:

const int array_size = 3;
int** m_array1[array_size];
int** m_array2[array_size];

其余的代码可以实现为:

void Delete1()
{
     for (int i = 0; i < array_size - 1; i++) // delete all memory but leave the last intact
     {
         if (*(int*)m_array1[i])
         {
             cout << "Delete1: erasing #" << i << " with mem addr " << std::hex << *m_array1[i] << std::dec << endl;
             delete *m_array1[i];
             *m_array1[i] = NULL;
         }
     }
}

void Delete2()
{
    for (int i = 0; i < array_size; i++)
    {
        if (*m_array2[i])
        {
            cout << "Delete2: erasing #" << i << " with mem addr " << std::hex << *m_array2[i] << std::dec << endl;
            delete *m_array2[i];
            *m_array2[i] = NULL;
        }
        else
        {
            cout << "Delete2: !!! memory at #" << i << " was already deleted." << endl;
        }
    }
}

int main()
{
    int* num1 = new int(10);
    int* num2 = new int(20);
    int* num3 = new int(30);

    cout << "main: storing " << std::hex << &num1 << " which points to " << num1 << std::dec << endl;
    cout << "main: storing " << std::hex << &num2 << " which points to " << num2 << std::dec << endl;
    cout << "main: storing " << std::hex << &num3 << " which points to " << num3 << std::dec << endl;

    m_array1[0] = &num1;
    m_array1[1] = &num2;
    m_array1[2] = &num3;

    m_array2[0] = &num1;
    m_array2[1] = &num2;
    m_array2[2] = &num3;

    Delete1();
    Delete2();
}

输出:

main: storing 0xbfc3818c which points to 0x87b6008
main: storing 0xbfc38188 which points to 0x87b6018
main: storing 0xbfc38184 which points to 0x87b6028
Delete1: erasing #0 with mem addr 0x87b6008
Delete1: erasing #1 with mem addr 0x87b6018
Delete2: !!! memory at #0 was already deleted.
Delete2: !!! memory at #1 was already deleted.
Delete2: erasing #2 with mem addr 0x87b6028

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM