在 C++ 中将对象数组设置为 null
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13114881/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Set array of object to null in C++
提问by Chin
Suppose I have an array of objects of type Foo in C++:
假设我在 C++ 中有一个 Foo 类型的对象数组:
Foo array[10];
In Java, I can set an object in this array to null simply by:
在 Java 中,我可以简单地将这个数组中的一个对象设置为 null:
array[0] = null //the first one
How can I do this in C++?
我怎样才能在 C++ 中做到这一点?
采纳答案by sampson-chen
Use pointers instead:
改用指针:
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.
Note that you need to consider memory management in C++ because unlike Java, it does not have a Garbage Collector that will automatically clean up memory for you when you set a reference to nullptr. Also, nullptr is the modern and proper C++ way to do it, as rather than always is a pointer type rather than just zero.
请注意,您需要考虑 C++ 中的内存管理,因为与 Java 不同,它没有垃圾收集器,当您设置对 nullptr 的引用时,它会自动为您清理内存。此外,nullptr 是现代且正确的 C++ 方法,因为它并不总是指针类型而不仅仅是零。
回答by Ed S.
So, forget Java here, it's not helping you. Ask yourself; what does it mean for an object to be null? Can an object be null? The answer is no, an objectcan not be null, but a reference (pointer in C++ terms) to one can be.
所以,在这里忘记 Java,它对你没有帮助。问你自己; 对象为空是什么意思?对象可以为空吗?答案是否定的,对象不能为空,但对一个对象的引用(C++ 术语中的指针)可以。
In java you have reference types, which are similar to pointers under the hood. However, you cannot set objectsto null even in java, only references.
在 Java 中,您有引用类型,它们类似于引擎盖下的指针。但是,即使在 Java 中也不能将对象设置为 null,只能设置为引用。
In C++ you have fully fledged objects and pointers and references to objects. A pointer to an object (or primitive type) can be null, but an object itself cannot.
在 C++ 中,您拥有完全成熟的对象以及对象的指针和引用。指向对象(或原始类型)的指针可以为 null,但对象本身不能。
So, when you create an array of Foo
objects you have, well, an array of Foo
objects. You don't have pointers, you have objects. If your array were an array of pointersto objects then yes, you could initialize them to null
(nullptr
in C++0x), i.e., they don't refer to a valid object.
所以,当你创建一个Foo
对象数组时,你有一个Foo
对象数组。你没有指针,你有对象。如果您的数组是指向对象的指针数组,那么是的,您可以将它们初始化为null
(nullptr
在 C++0x 中),即它们不引用有效对象。
回答by deinier
Other way that you have is using one dynamic array of pointers of Foo like this:
您拥有的另一种方法是使用一个动态的 Foo 指针数组,如下所示:
Foo** array = new Foo*[10];// Pointer of array of pointers.
Then you can initialize all this pointers to objects Foo
然后你可以初始化所有指向对象 Foo 的指针
for(int i=0;i<10;i++)
array[i] = new Foo();// Give memory to pointers of object Foo in array
assign null to one item of array:
将 null 分配给数组的一项:
array[0] = 0;
I think that in C++, NULL is 0. This means it can even be assigned to an int or anywhere a 0 is acceptable. Conventionally, it's only used with pointers.
我认为在 C++ 中,NULL 是 0。这意味着它甚至可以分配给 int 或任何可接受的 0。通常,它仅与指针一起使用。
For delete this memory:
要删除此内存:
for(int i=0;i<10;i++)
delete array[i];
and finally
最后
delete[] array;
Code Example:
代码示例:
#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;
}
回答by Tony Delroy
so is there away to "remove" an element in the array without creating a new one? i.e making a hole in the array of some sort?
那么是否可以在不创建新元素的情况下“删除”数组中的元素?即在某种数组中打一个洞?
In C++, if you have an array:
在 C++ 中,如果你有一个数组:
Foo array[10];
Then all 10 elements will be default-constructed. In general, there's no concept of array elements being in use vs. "removed". One way to track this idea is to make having actual values in the array elements optional, as in:
然后所有 10 个元素都将被默认构造。一般来说,没有使用数组元素与“已删除”的概念。跟踪这个想法的一种方法是将数组元素中的实际值设为可选,如下所示:
boost::optional<Foo> array[10];
You can read about the boost library's optional<>
library at http://www.boost.org/doc/libs/release/libs/optional/
您可以optional<>
在http://www.boost.org/doc/libs/release/libs/optional/阅读有关 boost 库的库
For the sake of documenting alternatives, I'll cover a hideous one. You could call the destructor on one of the elements: array[3].~Foo();
This is very dangerous as when the array itself goes out of scope, the destructor for each element will be called, and a precondition for that is to have a properly constructed object, so you have to be sure to have constructed a Foo in that element again beforehand (using "placement" new
). There is nothing in the array itself that will help you keep track of which elements have had their destructors called by you - you'd need to track that yourself (having some record of this inside the objects would probably work in practice, but accessing the object after destruction is undefined behaviour). You'd need to be very careful that in all code paths - including those due to exceptions - you tracked the momentarily unused array elements. You reallydon't want to do this.
为了记录替代方案,我将介绍一个可怕的替代方案。您可以在其中一个元素上调用析构函数:array[3].~Foo();
这是非常危险的,因为当数组本身超出范围时,将调用每个元素的析构函数,而前提条件是拥有一个正确构造的对象,因此您有确保事先在该元素中再次构造了一个 Foo(使用“放置”new
)。数组本身中没有任何内容可以帮助您跟踪哪些元素的析构函数被您调用 - 您需要自己跟踪(在对象内部记录一些此类记录可能在实践中有效,但访问销毁后的对象是未定义的行为)。您需要非常小心,在所有代码路径中 - 包括那些由于异常导致的 - 您跟踪暂时未使用的数组元素。你真的不想这样做。
If your concern is to remove an element from the array to save memory, then use smart pointers:
如果您关心的是从数组中删除一个元素以节省内存,那么使用智能指针:
shared_ptr<Foo> array[10];
You can then control specific array elements independently, with only still-populated elements being destructed when the element goes out of scope. Suitable smart pointers are available in boost or C++11, or you could use std::auto_ptr<>
but should carefully read about its semantics beforehand to see if it's suitable and how to safely use it.
然后,您可以独立控制特定的数组元素,只有在元素超出范围时才会销毁仍然填充的元素。合适的智能指针在 boost 或 C++11 中可用,或者你可以使用std::auto_ptr<>
但应该事先仔细阅读它的语义,看看它是否合适以及如何安全地使用它。
Separately, if there's a Foo::operator=(Some_Type*)
then you could set array[3] = NULL;
, and it would do whatever that assignment operator did to array[3]
. Still, if Foo
is not a pointer, it is probably a bad idea for it to allow someone to assign NULL
to it.
另外,如果有Foo::operator=(Some_Type*)
then 你可以设置array[3] = NULL;
,它会做任何赋值运算符对array[3]
. 尽管如此,如果Foo
不是一个指针,那么允许某人分配NULL
给它可能是一个坏主意。