簡體   English   中英

刪除向量中的指針后出現意外行為

[英]Unexpected behavior after deleting a pointer in a vector

我正在嘗試使用指針矢量,並遇到以下我不太了解的行為:

#include <iostream>
#include <vector>

int main()
{
    std::vector<int*> vec;

    int* p1 = new int;
    *p1 = 100;

    vec.push_back(p1);  
    std::cout << *vec[0] << std::endl;

    delete p1;
    std::cout << *vec[0] << std::endl;

    int* p2 = new int;
    *p2 = 200;

    std::cout << *vec[0] << std::endl;

    return 0;
}

使用MinGW C ++編譯器(g ++),這給了我以下輸出:

100
5640648
200

當然,現在刪除指針時並沒有刪除實際元素vec[0] ,但是請注意,向量中根本沒有插入p2 不過,打印第一個元素的值將返回此看似無關的指針的值! 另外,稍微重組代碼以便在刪除p1之前聲明p2不會產生此行為。

為了確保這一點,我還使用MSVC ++對其進行了編譯,從而獲得了以下(預期的)輸出:

100
5484120
5484120

有人對第一個輸出有解釋嗎?

因為刪除后訪問內存會導致未定義的行為:

delete p1;
std::cout << *vec[0] << std::endl;  <-- Buggy code

未定義的行為:-無法保證它將如何工作

它重新分配了p1保持的空間, vec[0]仍指向該空間,因此顯示了200值。

您已經注意到,這是一個編譯器的行為,而另一個編譯器的行為有所不同。 根據不同的優化開關,您可能還會有其他行為。 因此,總的來說,行為是不確定的,盡管有時我們可以弄清楚在特定情況下發生了什么。

您是否了解為什么這首先是未定義的行為

vec[0] 值為 p1 刪除p1之后; 取消引用vec [0]是非法的。 vec [0]只是指針p1的副本。

假設p1值為(地址)953241,由new返回,供您自由使用。 您存儲在該地址中的int值為100。但是,一旦刪除p1,就放棄了與該地址有關的所有權利。 您可以有效地將其返回給系統。 無法再閱讀。

delete p1 ,C ++釋放p1在堆上占用的空間,並將其用於其他數據。 因此,當您創建p2 ,會將其放到那里,因為它是它要使用的內存中的下一個位置。

vec[0]仍指向該位置,僅是因為指針中的數據仍位於堆棧中。 (C ++不知道您刪除了指針,但指針數據不會在任何地方,因此您仍然可以訪問它。下次在堆棧上執行任何操作時,它將被替換。)

我猜想MSVC ++故意不使用最近釋放的內存空間,因為它“更安全”-如果您偶然deleted某些內容然后改寫了它,那么它就永遠消失了。

delete p1;
std::cout << *vec[0] << std::endl; // (1.)

int* p2 = new int;
*p2 = 200;

std::cout << *vec[0] << std::endl; // (2.)

return 0;
  1. 您刪除了內存,因此未定義該地址的內容。
  2. g++輸出中,您會看到顯示了新值200,這是因為它位於

     int* p1 = new int; *p1 = 100; 

    代碼,請不要使用該值,因為該行為是特定於實現的,並且只顯示該值是因為您沒有更早地分配任何可以容納在釋放的內存空間中的內容。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM