【问题标题】:Set array of object to null in C++在 C++ 中将对象数组设置为 null
【发布时间】:2012-10-18 08:51:41
【问题描述】:

假设我在 C++ 中有一个 Foo 类型的对象数组:

Foo array[10];

在 Java 中,我可以简单地将这个数组中的一个对象设置为 null:

array[0] = null //the first one

如何在 C++ 中做到这一点?

【问题讨论】:

  • 你在自欺欺人。您没有在 Java 中将任何 object 设置为 null,因为(就像在 C++ 中一样)这完全没有意义。但是,Java 中的变量不是对象(而是对对象的引用)。 (顺便说一下,在 C++ 中,引用变量也不是对象。在 Java 中,对象永远不能是变量。)

标签: c++ arrays object null


【解决方案1】:

改用指针:

Foo *array[10];

// Dynamically allocate the memory for the element in `array[0]`
array[0] = new Foo();
array[1] = new Foo();

...

// Make sure you free the memory before setting 
// the array element to point to null
delete array[1]; 
delete array[0]; 

// Set the pointer in `array[0]` to point to nullptr
array[1] = nullptr;
array[0] = nullptr;

// Note the above frees the memory allocated for the first element then
// sets its pointer to nullptr. You'll have to do this for the rest of the array
// if you want to set the entire array to nullptr.

请注意,您需要考虑 C++ 中的内存管理,因为与 Java 不同,它没有垃圾收集器,当您设置对 nullptr 的引用时,它会自动为您清理内存。此外,nullptr 是现代且正确的 C++ 方法,因为它并不总是指针类型,而不仅仅是零。

【讨论】:

  • 我在这里看不到动态分配,尽管您认为会有动态分配是有道理的。但是,这是错误的; delete array[0]。当然,这会在第一个元素之后进行清理,但是其他元素呢?我认为与初学者打交道时最好非常清楚。 OP 可能会认为这意味着 delete array[0] 就是您所需要的,这是错误的。
【解决方案2】:

所以,在这里忘记 Java,它对您没有帮助。问你自己;对象为空意味着什么?对象可以为空吗?答案是否定的,object 不能为 null,但对 one 的引用(C++ 术语中的指针)可以。

在 java 中,您有引用类型,这类似于引擎盖下的指针。但是,即使在 java 中,也不能将 objects 设置为 null,只能设置引用。

在 C++ 中,您拥有成熟的对象、指针和对象引用。 指向对象(或原始类型)的指针可以为空,但对象本身不能。

因此,当您创建一个 Foo 对象数组时,您拥有一个 Foo 对象数组。你没有指针,你有对象。如果您的数组是指向对象的 指针 数组,那么可以,您可以将它们初始化为 null(C++0x 中的 nullptr),即它们不引用有效对象.

【讨论】:

  • 所以在我原来的情况下,即 Foo 对象的数组,有没有办法删除其中一个?我认为这没有意义,对吧?
  • @Chin:这没有意义,请注意这里的术语'delete 在 C++ 中具有非常特殊的含义,即释放动态分配的内存。我认为这里可能有更好的方法来解决您的问题,但您需要稍微扩展一下这个问题。
  • 那么是否可以在不创建新元素的情况下“删除”数组中的元素?即在某种数组中打一个洞?
  • @Chin:不,数组的大小在编译时是固定的。在我看来,您确实需要一个映射结构、一个向量或(很可能是错误的选择)一个指针数组。
【解决方案3】:

您拥有的另一种方法是使用一个动态的 Foo 指针数组,如下所示:

Foo** array = new Foo*[10];// Pointer of array of pointers.

然后你可以初始化所有指向对象 Foo 的 this 指针

for(int i=0;i<10;i++)
    array[i] = new Foo();// Give memory to pointers of object Foo in array

将 null 分配给数组的一项:

array[0] = 0;

我认为在 C++ 中,NULL 是 0。这意味着它甚至可以分配给 int 或任何可以接受 0 的地方。按照惯例,它只与指针一起使用。

删除这段记忆:

for(int i=0;i<10;i++)
    delete array[i];

最后

delete[] array;

代码示例:

#include <iostream.h>
#include <stdio.h>
class Foo
{
  private:
    int a;
  public:
    Foo()
    {
      a = 0;
    }
   void Set_V(int p){a = p;}
   int Get_V(){return a;}
};

int main()
{
  Foo **array = new Foo*[10];
  for(int i=0;i<10;i++)
   {
     array[i] = new Foo();
   }

  //array[0] = 0;
  for(int i=0;i<10;i++)
    array[i]->Set_V(i);
  for(int i=0;i<10;i++)
    cout<<array[i]->Get_V()<<endl;
  for(int i=0;i<10;i++)
    delete array[i];
  delete[] array;
  return 0;
}

【讨论】:

  • "and finally delete array" 应该是delete[] array...但是您还没有解释为什么指针数组本身应该动态分配...会显得不必要的麻烦。
  • 是的,你是对的,delete[] 数组;顺便说一句,这是另一种方法。我没有说这是唯一的方法,不同的是我有一个指向 Foo 指针数组的指针。
  • "将 null 分配给数组的一项:array[0] = 0;" - 最好先 delete 它,否则你会泄漏内存和 Foo 可能正在管理的任何其他资源。 +1 表示努力做到彻底。
  • 是的,你是对的。我只回答如何使用null。现在我正在运行一个我拥有的示例,我想与大家分享。也许它有帮助。我是新来的,我怀疑邮政编码如何。
  • 如果您将代码缩进 4 个空格,它将被识别并格式化为代码。对于非代码句子中间的代码,您可以在代码周围使用反引号(左单引号),如下所示:“virtual 关键字”。欢迎!
【解决方案4】:

那么是否可以在不创建新元素的情况下“删除”数组中的元素?即在某种数组中打一个洞?

在 C++ 中,如果你有一个数组:

Foo array[10];

那么所有 10 个元素都将被默认构造。一般来说,没有使用数组元素与“删除”的概念。跟踪这个想法的一种方法是让数组元素中的实际值是可选的,如下所示:

boost::optional<Foo> array[10];

您可以在 http://www.boost.org/doc/libs/release/libs/optional/ 阅读有关 boost 库的 optional&lt;&gt; 库的信息

为了记录替代方案,我将介绍一个可怕的替代方案。您可以在其中一个元素上调用析构函数:array[3].~Foo(); 这是非常危险的,因为当数组本身超出范围时,将调用每个元素的析构函数,前提是要有一个正确构造的对象,所以你必须确保事先在该元素中再次构造了一个 Foo (使用“放置”new)。数组本身没有任何内容可以帮助您跟踪哪些元素的析构函数被您调用 - 您需要自己跟踪(在对象内部有一些记录可能在实践中有效,但访问销毁后的对象是未定义的行为)。您需要非常小心,在所有代码路径中 - 包括由于异常导致的路径 - 您跟踪了暂时未使用的数组元素。你真的不想这样做。

如果您关心的是从数组中删除一个元素以节省内存,请使用智能指针:

shared_ptr<Foo> array[10];

然后,您可以独立控制特定的数组元素,当元素超出范围时,只有仍然填充的元素会被破坏。合适的智能指针在 boost 或 C++11 中可用,或者您可以使用 std::auto_ptr&lt;&gt;,但应事先仔细阅读其语义,看看它是否合适以及如何安全使用它。

另外,如果有Foo::operator=(Some_Type*),那么您可以设置array[3] = NULL;,它会执行该赋值运算符对array[3] 所做的任何事情。不过,如果Foo 不是指针,那么允许某人将NULL 分配给它可能是个坏主意。

【讨论】:

    猜你喜欢
    • 2018-11-05
    • 2020-07-16
    • 1970-01-01
    • 1970-01-01
    • 2010-10-09
    • 1970-01-01
    • 2012-09-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多