我正在学习指针,一个概念令我不安。 我知道如果你有一个INT类型的指针(例如'pointer1')指向一个数组,那么你可以用INTS填充该数组。如果你想要解决数组的一个成员,你可以使用指针,你可以做pointer1 ++;逐步完成数组。该程序知道它是一个INT数组,因此它知道在INT大小步骤中逐步执行。 但是如果数组的长度可以变化,那该怎么办呢?当你尝试用++增加时,它是如何知道该做什么的,因为每个元素的长度不同?
同样,当你创建一个字符串向量并使用reserve关键字时,如果字符串可以有不同的长度,它如何知道保留多少? 这可能是非常明显的但我无法解决它并且它不符合我当前(可能是错误的)对指针的思考。 感谢
答案 0 :(得分:10)
非常简单。
字符串数组与字符串向量不同。
字符串数组(C风格指针)是指向字符数组“char **”的指针数组。因此,字符串数组中的每个元素都具有“Pointer-to-char-array”的大小,因此它可以毫无问题地逐步执行stringarray中的元素。数组中的指针可以指向不同大小的内存块。
使用字符串向量,它是一个字符串对象数组(C ++样式)。每个字符串对象具有相同的对象大小,但在某处包含指向实际存储字符串内容的内存片段的指针。所以在这种情况下,向量中的元素大小也相同,但与“只是一个指向char数组的指针”不同,允许简单的元素地址计算。
答案 1 :(得分:6)
这是因为字符串(至少在C / C ++中)与整数不完全相同。如果我们正在谈论C风格的字符串,那么它们的数组就像
char* test[3] = { "foo", "bar", "baz" };
实际上发生的事情是“test”是一个指针数组,每个指针都指向字符所在的实际数据。让我们随机地说,“test”数组从内存地址0x10000开始,并且指针长度为4个字节,那么我们可能有
test[0] (memory location 0x10000) contains 0x10020
test[1] (memory location 0x10004) contains 0x10074
test[2] (memory location 0x10008) contains 0x10320
然后我们可以查看0x10020周围的内存位置,我们会找到实际的字符数据:
test[0][0] (memory location 0x10020) contains 'f'
test[0][1] (memory location 0x10021) contains 'o'
test[0][2] (memory location 0x10022) contains 'o'
test[0][3] (memory location 0x10023) contains '\0'
围绕内存位置0x10074
test[1][0] (memory location 0x10074) contains 'b'
test[1][1] (memory location 0x10075) contains 'a'
test[1][2] (memory location 0x10076) contains 'r'
test[1][3] (memory location 0x10077) contains '\0'
对于C ++ std :: string对象,情况大致相同:实际的C ++字符串对象不会“包含”字符,因为正如您所说,字符串的长度可变。它实际包含的是指向字符的指针。 (至少,它在std :: string的简单实现中实现 - 实际上它有一个更复杂的结构,以提供更好的内存使用和性能)。
答案 2 :(得分:0)
字符串数组是指向某些字符串的第一个字符的指针数组。指向char的指针大小可能与指向int的指针大小相同。
基本上,2D数组在内存中不一定是线性的,指向数组可以在任何地方。
答案 3 :(得分:0)
这可能看起来像是迂腐,但是像C ++这样的射击语言这很重要:在你原来的问题中你说:
你可以做pointer1 ++;逐步完成数组。
Postincrement(pointer1 ++)在这里通常是语义上错误的,因为它意味着“递增指针1,但将表达式值保持在pointer1的原始值”。如果您不需要pointer1的原始值,请使用pre-increment(++ pointer1),它在语义上完全是“将指针递增1”的含义。
出于某种原因,大多数C ++教科书都在各处做后增量教学,教导新的C ++ - 坏习惯; - )
答案 4 :(得分:0)
在C ++中,数组和向量总是包含固定大小的元素。字符串适合这种情况,因为你的字符串元素是指向存储在其他地方的以null结尾的c字符串(char *)的指针,或者是普通的std :: string对象。
std :: string对象的大小是常量,实际的字符串数据是在其他地方分配的(除了小字符串优化,但这是另一个故事)。
vector<string> a;
a.resize( 2 ); // allocate memory for 2 strings of any length.
vector<char *> b;
b.resize( 2 ); // allocate memory for 2 string pointers.
vector<char> c; // one string. Should use std::string instead.
c.resize( 2 ); // allocate memory for 2 characters (including or not the terminator).
请注意,std :: vector的reserve()函数只是准备向量增长。它主要用于优化目的。您可能想要使用resize()。