关于字符串文字和动态分配的两个基本C ++问题

时间:2009-01-11 22:21:50

标签: c++

这两个是等价的吗?

char * aString =“这是一个字符串。”;

char aString [] =“这是一个字符串。”;

根据我的理解,C ++按地址存储字符串,因此指针获取有效地址。我假设字符串也存储为char类型?但它如何知道为字符串分配多少内存?通常,char数组需要预设其数组大小。我相信在编译之前编译器会计算[]类型数组。这是字符串文字指针也会发生什么?

关于我的第二个问题,这两者之间的区别是什么:

int someNumber;

int * someNumber = new int;

第二个应该是动态分配。如果我理解了这个概念,它会在读取声明后立即分配内存。但标准声明中会发生什么?基本上,我需要了解动态分配如何优于标准声明。

5 个答案:

答案 0 :(得分:15)

char * aString = "This is a string.";

它使指针aString指向包含"This is a string."的静态分配的char数组。该字符串可写,即使指针的类型可能暗示您可以写入它。请参阅以下链接中的答案,了解避免它的原因以及如何做得更好。

char aString[] = "This is a string.";

它正在创建一个类型为char[18]的数组。即使您使用声明符告诉它aString具有类型char[],它实际上定义了一个具有完整类型的数组 - 即具有该数组的已定义长度。那是因为它是直接初始化的,编译器可以推断出数组的大小。数组 可写。您可以自由更改其中的字符。我试着在这个答案中明确区别:C++ strings: [] vs. *

int someNumber;

这是在堆栈上创建的整数变量。这是没有初始化。它具有自动存储持续时间:超出范围(从函数返回,突破循环...)将释放它的内存。您当然可以根据需要随意写信。

int * someNumber = new int;

它是一个指针,指向一个动态分配的整数。 int 已初始化。当指针超出范围时,内存被释放。也就是说,当你的函数返回时,内存仍然存在。

答案 1 :(得分:5)

char *aString = "This is a string.";

声明指向字符串的指针。也就是说,指向定义此字符串的数据段内存区域的指针。

char aString[] = "This is a string.";

在堆栈上声明一个字符数组,并将字符串的内容复制到其中。 与所有堆栈分配一样,您无法从函数返回变量。

int someNumber;

是否在堆栈上声明了一个整数。

int *someNumber = new int;

“new int”在堆上创建动态分配。并且“int * someNumber =”将地址分配给指向整数的指针。

对于动态分配,您需要记住在完成时调用delete以允许堆恢复内存或使用智能指针或类似内容。

答案 2 :(得分:1)

正确答案中有一些不清楚的事情。虽然char foo [] =“literal”;确实创建了一个可写的文本数组,每次函数启动时,它重置的文本都是:

void func() {
    char foo[] = "hello";

    cout << foo << endl;

    foo[2] = 'w';
    foo[3] = 'w';

    cout << foo << endl;
}

func();
func();

如果你跑了,你会得到:

hello
hewwo
hello
hewwo

字符串文字“hello”存储在应用程序的数据段中,当func到达声明foo的语句时,它将字符串从数据段复制到堆栈上。

另一方面,char * foo =“你好”;因为“你好”是一个限制值是非法的。你需要声明它const char * foo =“hello”;。这会直接创建一个指向存储在程序数据段中的数据的指针,并且未定义写入该数据。

如果丢弃你可以写入的常量。

void func() {
    const char* c_foo = "hello";
    char* foo = const_cast<char*>(c_foo);

    cout << foo << endl;

    foo[2] = 'w';
    foo[3] = 'w';

    cout << foo << endl;
}

hello
hewwo
hewwo
hewwo

最有可能的是,你会在所有后续调用func()时看到hewwo,如上所示。但是,对于现代多处理操作系统,如果程序运行的时间足够长,则可以换掉内存,当交换回来时,包含“hello”字符串的数据段将从磁盘上的程序可执行文件读取。下一次调用func可能会打印hello hewwo甚至hello hello或hello hewlo或hewwo hello或你能想到的任何其他组合,因为在执行过程中任何时候都可能出现时间片。

希望这不会太混乱。

答案 3 :(得分:-2)

对于第一个问题,编译器会计算字符串中的字符数并创建该大小的数组。 char * theString =“你好”;在堆上创建一个char数组。 char [] theString =“你好”;在堆栈上创建该数组。对于你的第二个问题int * thenum = new in;是动态的。标准声明在堆栈上存储数据,这意味着不必分配内存。内存分配可能是一个缓慢的过程,尤其是当堆碎片化时。堆栈空间有限,因此一般规则是在需要大量内存或需要指针的数据结构时使用动态分配,在需要变量或小对象时使用标准分配。

答案 4 :(得分:-3)

是的,在C语言类型中* foo等同于类型foo []。

静态变量在数据段的加载时分配,而动态变量在运行时分配在堆栈上。