我是C ++中的新手。我不确定为什么我需要像char * something[20]
这样的指针而不仅仅是char something[20][100]
。我意识到第二种方法意味着将为数组中的每个元素分配100块内存,但第一种方法不会引入内存泄漏问题。
如果有人能向我解释char * something[20]
如何找到记忆,那就太棒了。
编辑:
我的C ++ Primer Plus书正在做:
const char * cities[5] = {
"City 1",
"City 2",
"City 3",
"City 4",
"City 5"
}
这与人们刚刚说的相反吗?
答案 0 :(得分:5)
你在内存中分配了20个指针,然后你需要遍历每个指针以动态分配内存:
something[0] = new char[100];
something[1] = new char[20]; // they can differ in size
并将它们全部分开删除:
delete [] something[0];
delete [] something[1];
编辑:
const char* text[] = {"These", "are", "string", "literals"};
直接在源代码中指定的字符串(“字符串文字”,总是const char *
)与char *
完全不同,主要是因为您不必担心它们的alloc / dealloc 。它们在内存中的处理通常也非常不同,但这取决于编译器的实现。
答案 1 :(得分:2)
它将为20个char-pointers分配空间。
它们不会被初始化,因此典型用法看起来像
char * something[20];
for (int i=0; i<20; i++)
something[i] = strdup("something of a content");
以后
for (int i=0; i<20; i++)
if (something[i])
free(something[i]);
答案 2 :(得分:2)
你是对的。
您需要遍历该数组的每个元素并为每个元素分配一个字符缓冲区。
然后,稍后,您需要遍历该数组的每个元素并再次释放内存。
为什么你想用C ++来解决这个问题是有人猜的。
std::vector<std::string> myStrings(20)
出了什么问题?
答案 3 :(得分:0)
你是对的 - 第一种方法可能会引入内存泄漏问题和动态分配的开销,以及更多的读取。我认为第二种方法通常更可取,除非它浪费太多RAM或者你可能需要字符串长度超过99个字符。
第一种方法如何运作:
char* something[20]; // Stores 20 pointers.
something[0] = malloc(100); // Make something[0] point to a new buffer of 100 bytes.
sprintf(something[0], "hai"); // Make the new buffer contain "hai", going through the pointer in something[0]
free(something[0]); // Release the buffer.
答案 4 :(得分:0)
char* smth[20]
不会在堆上分配任何记忆。它在堆栈上分配足够的空间来存储20个指针。这些指针的值是未定义的,因此在使用它们之前,必须对它们进行初始化,如下所示:
char* smth[20];
smth[0] = new char[100]; // allocate memory for 100 chars, store the address of the first one in smth[0]
//..some code..
delete[] smth[0];
答案 5 :(得分:0)
首先,这个几乎在C ++中不适用。 C ++中的普通等价物类似于:std::vector<std::string> something;
在C中,主要区别在于您可以将每个字符串与其他字符串分开。使用char something[M][N]
,您始终会为每个字符串分配完全相同数量的字符串和相同的空间。这通常会浪费空间(当字符串短于你为空间设置的空间时),并且不允许你处理任何更多的字符串或更长的字符串,而不是你最初为空间腾出空间。
char *something[20]
让你更有效地处理更长/更短的字符串,但仍然只为20个字符串腾出空间。
下一步(如果你喜欢冒险)是使用类似的东西:
char **something;
并单独分配字符串,和也动态地为指针分配空间,所以如果你得到超过20个字符串,你也可以处理它。
但是,我会重复一遍,对于大多数实际目的,这仅限于C.在C ++中,标准库已经具有这些情况的数据结构。答案 6 :(得分:0)
C ++有指针,因为C有指针。
为什么我们使用指针?
跟踪动态分配的内存。 C中的内存分配函数(malloc
,calloc
,realloc
)和{{1 C ++中的运算符都返回指针值。
模仿传递引用语义(仅限C)。在C中,所有函数参数都按值传递;形式参数和实际参数是不同的对象,修改形式参数不会影响实际参数。我们通过传递指向函数的指针来解决这个问题。 C ++引入了引用类型,它们用于相同的目的,但比使用指针更清晰,更安全。
构建动态的自引用数据结构。 new
不能包含自身的实例,但它可以包含指针一个实例。例如,以下代码
struct
为简单的链表节点创建数据类型;
struct node
{
data_t data;
struct node *next;
};
成员显式指向列表中的下一个元素。请注意,在C ++中,堆栈,队列和向量的STL容器都使用引擎盖下的指针,将您与簿记隔离开来。
其他地方还有很多指针出现,但这些是你使用指针的主要原因。
您的指针数组可用于存储不同长度的字符串,方法是为每个字符分配足够的内存,而不是依赖于某些最大大小(最终会超出,导致缓冲区溢出错误,并且无论如何都会导致内部内存碎片)。当然,在C ++中你使用next
数据类型(它隐藏了类API背后的所有指针和内存管理)而不是指向string
的指针,但有人决定通过开始时混淆你低级细节而不是大局。
答案 7 :(得分:0)
我不是 确定为什么我需要像char *这样的指针 某事[20]反对只是char 一些[20] [100]。我意识到了 第二种方法意味着100 将分配内存块 但是,数组中的每个元素 不会第一种方法介绍 内存泄漏问题。
如果您只是在本地引用缓冲区,第二种方法就足够了。
将数组名称传递给另一个函数时会出现问题。当您将char something[10]
传递给另一个函数时,您实际上正在传递char* something
,因为数组长度不适合乘坐。
对于多维数组,您可以声明一个函数,该函数在除一个方向之外的所有方向上接收一个确定长度的数组,例如foo(char* something[10])
。
那么为什么要使用第一种形式而不是第二种形式?我可以想到几个原因:
答案 8 :(得分:0)
char * something [20]
假设这是32Bit,这将在堆栈上分配80个字节的数据。 每个指针地址4个字节,总共20个指针= 4 x 20 = 80个字节。
指针都是未初始化的,因此您需要编写额外的代码来分配/释放 这样做的缓冲区。
大致如下:
[0] [4个未初始化数据字节用于保存指针/内存地址...] [1] [4字节...] ... [19]
char something [20] [100]
在堆栈上分配2000个字节。 每个东西100个字节,总共20个东西= 100 x 20 = 2000个字节。
[0] [保存字符的100个字节] [1] [保存字符的100个字节] ... [19]
char *具有较小的内存开销,但您必须管理内存。 char [] []方法具有更大的内存开销,但您没有额外的内存管理。
无论采用哪种方法,在写入分配的缓冲区时都要小心,不要超过/覆盖为其分配的内存。