假设我在 C++ 中有一个 Foo 类型的对象数组:
Foo array[10];
在 Java 中,我可以简单地将这个数组中的一个对象设置为 null:
array[0] = null //the first one
我怎样才能在 C++ 中做到这一点?
改用指针:
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++ 方法,因为它并不总是指针类型,而不仅仅是零。
所以,在这里忘记Java,它对你没有帮助。问你自己; 对象为空意味着什么?对象可以为空吗?答案是否定的,一个对象不能为空,但一个对象的引用(C++ 术语中的指针)可以。
在 java 中,您有引用类型,它们类似于引擎盖下的指针。但是,即使在 java 中,也不能将对象设置为 null,只能设置引用。
在 C++ 中,您拥有完全成熟的对象以及对对象的指针和引用。指向对象(或原始类型)的指针可以是 null ,但对象本身不能。
所以,当你创建一个Foo
对象数组时,你有一个Foo
对象数组。你没有指针,你有对象。如果您的数组是指向对象的指针数组,那么可以,您可以将它们初始化为null
(nullptr
在 C++0x 中),即它们不引用有效对象。
您拥有的另一种方法是使用一个动态的 Foo 指针数组,如下所示:
Foo** array = new Foo*[10];// Pointer of array of pointers.
然后你可以初始化所有指向对象 Foo 的指针
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;
}
那么是否可以在不创建新元素的情况下“删除”数组中的元素?即在某种数组中打一个洞?
在 C++ 中,如果你有一个数组:
Foo array[10];
然后所有 10 个元素将被默认构造。一般来说,没有数组元素正在使用与“删除”的概念。跟踪这个想法的一种方法是让数组元素中的实际值是可选的,如下所示:
boost::optional<Foo> array[10];
您可以在http://www.boost.org/doc/libs/release/libs/optional/阅读有关 boost 库的optional<>
库
为了记录替代方案,我将介绍一个可怕的替代方案。您可以在其中一个元素上调用析构函数:array[3].~Foo();
这是非常危险的,因为当数组本身超出范围时,将调用每个元素的析构函数,并且前提条件是要有一个正确构造的对象,所以你有确保事先在该元素中再次构造了一个 Foo (使用“放置”new
)。数组本身没有任何内容可以帮助您跟踪哪些元素的析构函数已被您调用 - 您需要自己跟踪(在对象中对此进行一些记录可能在实践中有效,但访问销毁后的对象是未定义的行为)。您需要非常小心,在所有代码路径中 - 包括由于异常而导致的路径 - 您跟踪了暂时未使用的数组元素。你真的不想这样做。
如果您关心的是从数组中删除一个元素以节省内存,请使用智能指针:
shared_ptr<Foo> array[10];
然后,您可以独立控制特定的数组元素,当元素超出范围时,只有仍然填充的元素被破坏。合适的智能指针在 boost 或 C++11 中可用,或者您可以使用std::auto_ptr<>
,但应该事先仔细阅读它的语义,看看它是否合适以及如何安全地使用它。
另外,如果有一个Foo::operator=(Some_Type*)
then 你可以设置array[3] = NULL;
,它会做任何赋值运算符对array[3]
. 尽管如此,如果Foo
不是一个指针,允许某人分配NULL
给它可能是一个坏主意。