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