2017-04-14 133 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动态分配对象和对象直接包含的所有内容。在你写对象声明的方式和它是“在堆上”还是“在堆栈上”之间的任何心理联系都注定要失败。

确定对象存储时间长度的唯一可靠方法是了解其历史记录;唯一可靠的方法来确定一个对象的存储位置是不打扰,因为你不需要。