C++ 删除参考
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3233987/
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
Deleting a reference
提问by Newton Falls
Is this valid? An acceptable practice?
这是有效的吗?一种可接受的做法?
typedef vector<int> intArray;
intArray& createArray()
{
intArray *arr = new intArray(10000, 0);
return(*arr);
}
int main(int argc, char *argv[])
{
intArray& array = createArray();
//..........
delete &array;
return 0;
}
回答by David Rodríguez - dribeas
The behavior of the code will be your intended behavior. Now, the problem is that while you might consider that programming is about writing something for the compiler to process, it is just as much about writing something that other programmers (or you in the future) will understand and be able to maintain. The code you provided in many cases will be equivalent to using pointers for the compiler, but for other programmers, it will just be a potential source of errors.
代码的行为将是您预期的行为。现在,问题是,虽然您可能认为编程是编写一些供编译器处理的东西,但编写其他程序员(或将来的您)将理解并能够维护的东西也同样重要。你提供的代码在很多情况下对于编译器来说相当于使用指针,但对于其他程序员来说,这只是一个潜在的错误来源。
References are meant to be aliases to objects that are managed somewhere else, somehow else. In general people will be surprised when they encounter delete &ref
, and in most cases programmers won't expect having to perform a delete
on the address of a reference, so chances are that in the future someone is going to call the function an forget about deleting and you will have a memory leak.
引用旨在成为在其他地方以其他方式管理的对象的别名。一般来说,人们在遇到 时会感到惊讶delete &ref
,并且在大多数情况下,程序员不会期望必须对delete
引用的地址执行 a ,因此将来可能有人会调用该函数而忘记删除,而您会有内存泄漏。
In most cases, memory can be better managed by the use of smart pointers (if you cannot use other high level constructs like std::vector
s). By hiding the pointer away behind the reference you are making it harder to use smart pointers on the returned reference, and thus you are not helping but making it harder for users to work with your interface.
在大多数情况下,可以通过使用智能指针更好地管理内存(如果您不能使用其他高级构造,如std::vector
s)。通过将指针隐藏在引用后面,您将更难在返回的引用上使用智能指针,因此您不仅没有帮助,反而使用户更难使用您的界面。
Finally, the good thing about references is that when you read them in code, you knowthat the lifetime of the object is managed somewhere else and you need not to worry about it. By using a reference instead of a pointer you are basically going back to the single solution (previously in C only pointers) and suddenly extra care must be taken with all references to figure out whether memory must be managed there or not. That means more effort, more time to think about memory management, and less time to worry about the actual problem being solved -- with the extra strain of unusual code, people grow used to look for memory leaks with pointers and expect none out of references.
最后,引用的好处是当你在代码中阅读它们时,你知道对象的生命周期是在其他地方管理的,你不必担心它。通过使用引用而不是指针,您基本上会回到单一解决方案(以前仅在 C 中使用指针),突然之间必须格外小心地处理所有引用,以确定是否必须在那里管理内存。这意味着更多的努力,更多的时间来考虑内存管理,而更少的时间担心正在解决的实际问题——由于异常代码的额外压力,人们习惯于使用指针查找内存泄漏,并期望没有引用.
In a few words: having memory held by reference hides from the user the requirement to handle the memory and makes it harder to do so correctly.
简而言之:通过引用保存内存对用户隐藏了处理内存的要求,并使其更难正确执行。
回答by Mark Ransom
Yes, I think it will work. But if I saw something like this in any code I worked on, I would rip it out and refactor right away.
是的,我认为它会起作用。但是如果我在我处理的任何代码中看到类似的东西,我会立即将其撕掉并重构。
If you intend to return an allocated object, use a pointer. Please!
如果您打算返回分配的对象,请使用指针。请!
回答by Billy ONeal
It's valid... but I don't see why you'd ever want to do it. It's not exception safe, and std::vector
is going to manage the memory for you anyway. Why new
it?
这是有效的......但我不明白你为什么想要这样做。它不是异常安全的,std::vector
无论如何都会为您管理内存。为什么new
呢?
EDIT: If you are returning new'd memory from a function, you should return the pointer, lest users of your function's heads explode.
编辑:如果您要从函数返回新的内存,则应返回指针,以免函数头部的用户爆炸。
回答by utnapistim
Is this valid?
这是有效的吗?
Yes.
是的。
An acceptable practice?
一种可接受的做法?
No.
不。
This code has several problems:
这段代码有几个问题:
The guideline of designing for least surprising behavior is broken: you return something that "looks like" an object but must be deleted by the client code (that should mean a pointer - a reference should be something that always points to a valid object).
your allocation can fail. Even if you check the result in the allocating function, what will you return? An invalid reference? Do you rely on the allocation throwing an exception for such a case?
设计最不令人惊讶的行为的准则被打破:您返回的东西“看起来像”一个对象,但必须被客户端代码删除(这应该意味着一个指针 - 一个引用应该是总是指向一个有效对象的东西)。
您的分配可能会失败。即使你在分配函数中检查结果,你会返回什么?无效的参考?在这种情况下,您是否依赖于抛出异常的分配?
As a design principle, consider either creating a RAII object that is responsible for managing the lifetime of your object (in this case a smart pointer) or deleting the pointer at the same abstraction level that you created it:
作为设计原则,请考虑创建一个负责管理对象生命周期的 RAII 对象(在本例中为智能指针),或者在创建它的同一抽象级别删除指针:
typedef vector<int> intArray;
intArray& createArray()
{
intArray *arr = new intArray(10000, 0);
return(*arr);
}
void deleteArray(intArray& object)
{
delete &object;
}
int main(int argc, char *argv[])
{
intArray& array = createArray();
//..........
deleteArray(array);
return 0;
}
This design improves coding style consistency (allocation and deallocation are hidden and implemented at the same abstraction level) but it would still make more sense to work through a pointer than a reference (unless the fact that your object is dynamically allocated mustremain an implementation detail for some design reason).
这种设计提高了编码风格的一致性(分配和释放被隐藏并在同一抽象级别实现),但通过指针工作仍然比通过引用更有意义(除非你的对象是动态分配的事实必须保留一个实现细节出于某种设计原因)。
回答by Validus Oculus
It is valid because compiler can compile and run successfully. However, this kind of coding practices makes codes more harder for readers and maintainers because of
它是有效的,因为编译器可以成功编译和运行。然而,这种编码实践使得代码对于读者和维护者来说更加困难,因为
- Manual memory management
- Vague ownership transfer to client side
- 手动内存管理
- 模糊的所有权转移到客户端
But there is a subtle point in this question, it is efficiency requirement. Sometimes we can not return pass-by value because object size might be too big, bulky as in this example (1000 * sizeof(int)); For that reason; we should use pointers if we need to transfer objects to different parts of our code. But this doesn't means above implementation is acceptable because for this kind of requirements, there is very useful tool, it is smart-pointers. So, design decision is up to programmer but for this kind of specific implementation details, programmer should use acceptable patterns like smart-pointers in this example.
但是这个问题有一个微妙的点,那就是效率要求。有时我们不能返回传递值,因为对象大小可能太大,像这个例子中那样笨重 (1000 * sizeof(int));是因为; 如果我们需要将对象传输到代码的不同部分,我们应该使用指针。但这并不意味着上面的实现是可以接受的,因为对于这种需求,有一个非常有用的工具,它是smart-pointers。所以,设计决定取决于程序员,但对于这种特定的实现细节,程序员应该使用可接受的模式,如本例中的智能指针。
回答by Owen S.
It will work but I'm afraid it's flat-out unacceptable practise. There's a strong convention in the C++ world that memory management is done with pointers. Your code violates this convention, and is liable to trip up just about anyone who uses it.
它会起作用,但恐怕这是完全不可接受的做法。在 C++ 世界中有一个强大的约定,即内存管理是用指针完成的。你的代码违反了这个约定,几乎任何使用它的人都会绊倒。
It seems like you're going out of your way to avoid returning a raw pointer from this function. If your concern is having to check repeatedly for a valid pointer in main, you can use a reference for the processing of your array. But have createArray return a pointer, and make sure that the code which deletes the array takes it as a pointer too. Or, if it's really as simple as this, simply declare the array on the stack in main and forego the function altogether. (Initialization code in that case could take a reference to the array object to be initialized, and the caller could pass its stack object to the init code.)
似乎您正在竭尽全力避免从此函数返回原始指针。如果您担心必须重复检查 main 中的有效指针,您可以使用引用来处理数组。但是让 createArray 返回一个指针,并确保删除数组的代码也将其作为指针。或者,如果真的像这样简单,只需在 main 中声明堆栈上的数组并完全放弃该函数。(在这种情况下,初始化代码可以引用要初始化的数组对象,调用者可以将其堆栈对象传递给初始化代码。)