用C ++指向对象的指针 - 堆栈/堆上有什么?

时间:2012-01-08 22:37:17

标签: c++ object pointers stack heap

我从Java开始,所以我对以下行中的堆栈/堆发生了什么感到困惑:

string *x = new string("Hello");

其中x是局部变量。在C ++中,对于该语句,堆栈上是否会发生任何事情?我知道从阅读它说对象是在堆上,但是x呢?在Java中,x只是在堆栈中,只保存指向对象的内存地址,但我没有找到一个明确的来源,说明C ++中发生了什么。

4 个答案:

答案 0 :(得分:3)

您刚刚创建的任何对象,例如您示例中的x位于堆栈中。但是,对象x只是一个指针,指向使用string放在堆上的堆new string("Hello")。通常,您不会在C ++中创建这样的字符串。相反,你会使用

string x("Hello");

这仍然会在堆栈上分配x。表示x的值的字符是否也存在于堆栈上,而不是堆上,取决于string实现。作为一个合理的模型,你应该假设它们在堆上(一些std::string实现将短字符串放入堆栈对象,避免任何堆分配并帮助处理局部性。)

答案 1 :(得分:2)

是的,x在堆栈上:它是一个局部变量,它们都在堆栈中。

new运算符会激活堆上的内存分配。

答案 2 :(得分:2)

与Java相同。 stringString位于堆上,而指针(或Java中的引用)位于堆栈中。

在Java中,所有对象都在堆上,堆栈只由原始类型和引用本身组成。 (堆栈有其他东西,如返回地址等,但不要紧,)。

C ++堆栈和Java堆栈之间的主要区别在于,在C ++中,您可以将整个对象直接放到堆栈上。例如string x = string("Hello");

在C ++中,也可以将原始类型直接放到堆上。例如int * x = new int();。 (换句话说,“如果自动装箱是解决方案,那么问题是什么?”)

简而言之,Java在原始类型和对象之间有着严格的区别,而原语是非常二等的。 C ++更加轻松。

答案 3 :(得分:0)

这取决于该线的位置。如果它位于文件范围的某个位置(即函数之外),那么x是一个全局变量,它肯定在堆栈上(理论上它可以放在调用main()之前的堆栈,但我强烈怀疑任何编译器都这样做了),但也没有在堆上。但是,如果该行是函数的一部分,那么确实x在堆栈中。

由于x的类型为string*(即指向字符串的指针),因此它实际上只包含用new分配的字符串对象的地址。由于该字符串对象分配有new,因此它确实存在于堆上。

但请注意,与Java不同,不需要内置类型存在于堆栈中,类对象存在于堆上。以下是生活在堆上的指针示例,指向生活在堆栈中的对象:

int main()
{
  std::string str("Hello"); // a string object on the stack
  std::string** ptr = new std::string*(&str); // a pointer to string living on the heap, pointing to str
  (**ptr) += " world"; // this adds "world" to the string on the stack
  delete ptr; // get rid of the pointer on the heap
  std::cout << str << std::endl; // prints "Hello world"
} // the compiler automatically destroys str here