問題描述
我是 C++ 的新手,到目前為止,當您對指向在堆上創建的內容的指針調用 delete 時,我學到了什么,然后該指針指向的任何內容都會被擦除并釋放內存,對嗎?
I'm new to C++ and from what I learned so far when you call delete on a pointer that points to something created on the heap then whatever is pointed by that pointer gets erased and the memory is freed, right?
然而,當我在一個簡單的類上嘗試這個時:
However when I tried this on a simple class:
class MyClass
{
int _Id;
public:
MyClass(int id) : _Id(id)
{
std::cout << "$Constructing the damn thing! " << _Id << std::endl;
}
~MyClass()
{
std::cout << "?Destructing the damn thing! " << _Id << std::endl;
}
void Go_XXX_Your_Self()
{
std::cout << "%OooooooooO NOOOOOO! " << _Id << std::endl;
delete this;
}
void Identify_Your_Self()
{
std::cout << "#Object number: " << _Id << " Located at: " << this << std::endl;
}
};
這些只是一些愚蠢的測試來看看刪除是如何工作的:
These are just some stupid tests to see how delete works:
int main()
{
MyClass* MC1 = new MyClass(100);
MyClass* MC2 = new MyClass(200);
MyClass* MC3 = MC2;
std::cout << MC1 << " " << MC2 << " " << MC3 << " " << std::endl;
MC1->Identify_Your_Self();
MC2->Identify_Your_Self();
MC3->Identify_Your_Self();
delete MC1;
MC1->Identify_Your_Self();
MC3->Go_XXX_Your_Self();
MC3->Identify_Your_Self();
delete MC2;
MC2->Identify_Your_Self();
MC2->Go_XXX_Your_Self();
MC2->Identify_Your_Self();
return 0;
}
輸出如下:
$Constructing the damn thing! 100
$Constructing the damn thing! 200
0x3e3e90 0x3e3eb0 0x3e3eb0
#Object number: 100 Located at: 0x3e3e90
#Object number: 200 Located at: 0x3e3eb0
#Object number: 200 Located at: 0x3e3eb0
?Destructing the damn thing! 100
#Object number: 0 Located at: 0x3e3e90
%OooooooooO NOOOOOO! 200
?Destructing the damn thing! 200
#Object number: 4079248 Located at: 0x3e3eb0
?Destructing the damn thing! 4079248
#Object number: 4079280 Located at: 0x3e3eb0
%OooooooooO NOOOOOO! 4079280
?Destructing the damn thing! 4079280
#Object number: 4079280 Located at: 0x3e3eb0
那么,我的問題是,為什么即使在對象被刪除后我仍然能夠調用 Go_XXX_Your_Self() 和 Identification_Your_Self()?
So, my question is, why I'm still able to call Go_XXX_Your_Self() and Identify_Your_Self() even after the object was deleted?
這是在 C++ 中的工作方式嗎?(刪除后還有嗎?)
Is this how it works in C++? (is there even after you delete it?)
你也可以檢查一下它是否在那里嗎?(我知道理論上是不可能的,但我很想知道那里有哪些方法)
Also can you check to see if it's not there? (I know theoretically is not possible but I'm curious to see what methods are out there)
推薦答案
那么,我的問題是,為什么即使在對象被刪除后我仍然能夠調用 Go_XXX_Your_Self() 和 Identification_Your_Self()?
So, my question is, why I'm still able to call Go_XXX_Your_Self() and Identify_Your_Self() even after the object was deleted?
因為未定義的行為.
這是在 C++ 中的工作方式嗎?(刪除后還有嗎?)
Is this how it works in C++? (is there even after you delete it?)
因為未定義的行為.不能保證它在其他實現上也能正常工作.同樣,未定義行為.
Because of undefined behavior. There is no guarantee that it will work the same on other implementations. Again, undefined behavior.
你也可以檢查一下它是否在那里嗎?(我知道理論上是不可能的,但我很想知道那里有哪些方法)
Also can you check to see if it's not there? (I know theoretically is not possible but I'm curious to see what methods are out there)
delete MC1;
MC1 = nullptr;
通過在 delete
之后將指針設置為 nullptr
,運行時最有可能檢測到您正在訪問一個無效的,您沒有權利-使用位置.此外,通過對所有適用的指針認真執行此操作,您可以檢查對象是否有效(如果非nullptr
則有效).
By setting the pointer to nullptr
after delete
ing it, the runtime is most likely to detect that you are accessing an invalid, you-have-no-right-to-use location. Also, by diligently doing this for all applicable pointers, you have the ability to check if the object is valid or not (valid if non-nullptr
).
if(my_ptr) {
// my_ptr is most possibly valid (though you can still go wrong)
// use my_ptr
}
同樣,當原始指針尚未初始化為某個有效地址時,您也應該將它們設置為 nullptr
.
Similarly, you should also set raw pointers to nullptr
when they aren't yet initialized to some valid address.
MyClass* some_ptr = nullptr;
...
但同樣,如果您可以訪問現代 C++11 工具,最好根本不使用原始指針,而只使用 std::unique_ptr
或 std::shared_ptr
(取決于您所需的語義).在未來的 C++ 標準修訂版中,您可能還想使用 建議的 std::exempt_ptr
這是一個非擁有的、僅觀察的指針包裝器.
But again, if you have access to modern C++11 facilities, it's much better not to use raw pointers at all, and just use std::unique_ptr
or std::shared_ptr
(depending on your required semantics). And on future C++ standard revisions, you may also want to use the proposed std::exempt_ptr
which is a non-owning, observe-only pointer wrapper.
這篇關于為什么即使在對象被刪除后我仍然可以訪問成員函數?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!