取决于你的意思。任何时候你有一个指针,都可以调用delete
它。
如果你有引用,你可以获取它的地址,它会给你一个指针
无论如何,如果你有这个类,例如:
class X {
int getByVal() { return i; } // returns a copy of i
int& getByRef() { return i; } // returns a reference to i
private:
int i;
};
那么我,作为您班级的用户,没有明显的方法来删除您的数据。我可以执行以下操作:
X x;
int j = x.getByVal();
int& k = x.getByRef();
j = 42; // doesn't affect x.i because we returned a copy
k = 42; // sets x.i to 42, because k is a reference
而且我没有明显的方法来删除班级成员。当然,我可以这样做:
delete &j;
delete &k;
(当然,这些都不会做任何有意义的事情,但它们会编译)但我不会偶然这样做。如果你不返回一个指针,很明显我不应该拥有数据的所有权。
“保护你的代码免受墨菲,而不是马基雅维利”通常是一个很好的经验法则。如果有人尝试,您无法阻止他们破坏您的代码。您应该担心的是防止他们意外地这样做。
编辑
针对您在问题下的评论:
正如我所说,我正在学习......副本认为被调用者必须释放返回变量的内存,这对被调用者来说更麻烦(甚至认为是我=p),所以我不是在谈论概念,但是写起来很容易……再说一次,我是这个记忆东西的新手。我在用 C#、PHP 等进行开发。我很久以前在用 CircleMUD 学习的时候用 C 开发
不,副本不必手动删除。局部变量超出范围时会自动删除。所以在上面的例子中,j
是类成员的副本i
。当调用函数返回时,j
会被自动删除。
希望有帮助。C++ 中的变量生命周期规则并不是很复杂,但是正确使用它们非常重要,因为很多代码都依赖于它们。
void foo()
{
int i = 0; // allocate a local (on the stack) int, and initialize it to 0
int* p = new int(1); // allocate an int on the heap, and initialize it to 1
int j = i; // create a *copy* of i. Now we have two ints on the stack
int k = *p; // create a copy of the int pointed to by p. k is also on the stack, so even though it was copied from a heap-allocated variable, k does not have to be manually deleted
int* q = p; // create a copy of p. q is not a separate pointer, which points to the *same* heap-allocated integer.
}
foo
在上面的例子中,所有的副本在返回时都会被自动清理。我们唯一需要手动做的就是删除我们在堆上分配的整数。两者都p
指向q
它,但我们只能删除对象一次。但是i
, j
, k
, p
, 和q
都是局部变量,声明在栈上。当函数返回时,它们中的每一个都会被清除。对于原始类型(例如int
s 和指针),实际上不需要发生任何事情(它们没有析构函数)。当它们超出范围时,它们就会消失——即使它们指向一些重要的东西,比如堆分配的对象,比如我们的整数。
对于非 POD 对象,当它们超出范围时,会调用它们的析构函数,因此它们也可以自行清理干净。因此,即使我们使用了比 更复杂的类型int
,上面的方法也可以正常工作。我们仍然可以复制非 POD 对象并按值传递它们。
我希望这有助于澄清一些事情。