2017-04-14 204 views
0

我開始學習動態內存分配的主題。C++堆棧/堆棧。爲什麼只有一個新操作員?

我有以下代碼:

#include <iostream> 
#include "A.h" 
#include "B.h" 

using namespace std; 

int main() { 

    /* Both objects on Stack */ 

    A classAStack; 
    B classBStack; 

    /* Both objects on Heap*/ 
    // A *classAHeap = new A(); 
    // B *classBHeap = new B(); 

    /* A objects on Heap B ???*/ 
    A *classAHeap = new A(); 

    return 0; 
} 

#ifndef A_H_ 
#define A_H_ 

#include <iostream> 
#include "B.h" 

class A { 
public: 
    A(); 
    virtual ~A(); 

public: 
    B b; 
}; 

#endif /* A_H_ */ 

#include "A.h" 

A::A() { 
    std::cout <<"Constructor A called" << std::endl; 
} 

A::~A() { 
} 

#ifndef B_H_ 
#define B_H_ 

#include <iostream> 

class B { 
public: 
    B(); 
    virtual ~B(); 
}; 

#endif /* B_H_ */ 

#include "B.h" 

B::B() { 
    std::cout <<"Constructor B called" << std::endl; 
} 

B::~B() { 
} 

調試器的輸出是:

 
Temporary breakpoint 6, main() at ../src/HeapStackTest02.cpp:18 
18 A classAStack; 

Breakpoint 4, B::B (this=0x23aa58) at ../src/B.cpp:12 
12 std::cout <<"Constructor B called" << std::endl; 

Breakpoint 5, A::A (this=0x23aa50) at ../src/A.cpp:13 
13 std::cout <<"Constructor A called" << std::endl; 

Breakpoint 4, B::B (this=0x23aa40) at ../src/B.cpp:12 
12 std::cout <<"Constructor B called" << std::endl; 

Breakpoint 4, B::B (this=0x60004b048) at ../src/B.cpp:12 
12 std::cout <<"Constructor B called" << std::endl; 

Breakpoint 5, A::A (this=0x60004b040) at ../src/A.cpp:13 
13 std::cout <<"Constructor A called" << std::endl; 

Breakpoint 1, main() at ../src/HeapStackTest02.cpp:30 
30 return 0; 

我的問題:

在哪裏成員變量A類的b

如果我看看0x23a部分的地址,它似乎是堆棧,而0x6000部分似乎是堆。

我正在使用Windows 64位系統。

爲什麼成員變量b也在堆上,沒有調用new運算符?

+6

'A :: b'是'A'的成員,所以它的存儲位於'A'的存儲區內。如果'A'在堆上,那麼它的所有成員都必然在堆上。 –

回答

0

考慮一下:

#include <iostream> 
#include <string> 

class B { 
public: 
    int64_t x = 42; 
    int64_t y = 7; 
}; 

class A1 { 
public: 
    B b; 
}; 

class A2 { 
public: 
    A2() { b = new B(); } 
    B* b; 
    ~A2() { delete b; } 
}; 

int main() { 
    std::cout << sizeof(A1) << std::endl; // prints 16 
    std::cout << sizeof(A2) << std::endl; // prints 8 

    // Section (2) 
    A1 a1; // Instance of A1 and B are on the stack 
    A2 a2; // Instance of A2 is on the stack. B is on the heap. 

    A1* a3 = new A1(); 
    std::cout << a3 == &(a3->b) << std:: endl; // prints true 

    A2* a4 = new A2(); 
    std::cout << a4 == a4->b << std::endl; // prints false 

    return 0; 
} 
0

成員是b是你動態分配對象的一部分,所以它是動態分配的一部分,是在內存中的相同位置。

如果成員不是對象的一部分,會留下什麼?你會有什麼動態分配?

這就是爲什麼當你看到new時,你應該避免使用術語「在堆上」。這不僅僅是你在「堆上」的事情。不,new動態分配對象和對象直接包含的所有內容。在你寫對象聲明的方式和它是「在堆上」還是「在堆棧上」之間的任何心理聯繫都註定要失敗。

確定對象存儲時間長度的唯一可靠方法是瞭解其歷史記錄;唯一可靠的方法來確定一個對象的存儲位置是不打擾,因爲你不需要。