我从Java开始,所以我对以下行中的堆栈/堆发生了什么感到困惑:
string *x = new string("Hello");
其中x
是局部变量。在C ++中,对于该语句,堆栈上是否会发生任何事情?我知道从阅读它说对象是在堆上,但是x
呢?在Java中,x
只是在堆栈中,只保存指向对象的内存地址,但我没有找到一个明确的来源,说明C ++中发生了什么。
答案 0 :(得分:3)
您刚刚创建的任何对象,例如您示例中的x
位于堆栈中。但是,对象x
只是一个指针,指向使用string
放在堆上的堆new string("Hello")
。通常,您不会在C ++中创建这样的字符串。相反,你会使用
string x("Hello");
这仍然会在堆栈上分配x
。表示x
的值的字符是否也存在于堆栈上,而不是堆上,取决于string
实现。作为一个合理的模型,你应该假设它们在堆上(一些std::string
实现将短字符串放入堆栈对象,避免任何堆分配并帮助处理局部性。)
答案 1 :(得分:2)
是的,x
在堆栈上:它是一个局部变量,它们都在堆栈中。
new
运算符会激活堆上的内存分配。
答案 2 :(得分:2)
与Java相同。 string
或String
位于堆上,而指针(或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