C ++指针问题

时间:2011-05-02 14:31:43

标签: c++ c

我是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"
}

这与人们刚刚说的相反吗?

9 个答案:

答案 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有指针。

为什么我们使用指针?

  1. 跟踪动态分配的内存。 C中的内存分配函数(malloccallocrealloc)和{{1 C ++中的运算符都返回指针值。

  2. 模仿传递引用语义(仅限C)。在C中,所有函数参数都按值传递;形式参数和实际参数是不同的对象,修改形式参数不会影响实际参数。我们通过传递指向函数的指针来解决这个问题。 C ++引入了引用类型,它们用于相同的目的,但比使用指针更清晰,更安全。

  3. 构建动态的自引用数据结构。 new不能包含自身的实例,但它可以包含指针一个实例。例如,以下代码

    struct
    为简单的链表节点创建数据类型; struct node { data_t data; struct node *next; }; 成员显式指向列表中的下一个元素。请注意,在C ++中,堆栈,队列和向量的STL容器都使用引擎盖下的指针,将您与簿记隔离开来。

  4. 其他地方还有很多指针出现,但这些是你使用指针的主要原因。

    您的指针数组可用于存储不同长度的字符串,方法是为每个字符分配足够的内存,而不是依赖于某些最大大小(最终会超出,导致缓冲区溢出错误,并且无论如何都会导致内部内存碎片)。当然,在C ++中你使用next数据类型(它隐藏了类API背后的所有指针和内存管理)而不是指向string的指针,但有人决定通过开始时混淆你低级细节而不是大局。

答案 7 :(得分:0)

  

我不是   确定为什么我需要像char *这样的指针   某事[20]反对只是char   一些[20] [100]。我意识到了   第二种方法意味着100   将分配内存块   但是,数组中的每个元素   不会第一种方法介绍   内存泄漏问题。

如果您只是在本地引用缓冲区,第二种方法就足够了。

将数组名称传递给另一个函数时会出现问题。当您将char something[10]传递给另一个函数时,您实际上正在传递char* something,因为数组长度不适合乘坐。

对于多维数组,您可以声明一个函数,该函数在除一个方向之外的所有方向上接收一个确定长度的数组,例如foo(char* something[10])

那么为什么要使用第一种形式而不是第二种形式?我可以想到几个原因:

  1. 您不希望限制整个缓冲区必须驻留在连续内存中。
  2. 您不知道在编译时您是否需要每个缓冲区,或者每个缓冲区的长度需要相同的大小,并且您希望在运行时灵活地确定它。
  3. 这是一个功能声明。

答案 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 [] []方法具有更大的内存开销,但您没有额外的内存管理。

无论采用哪种方法,在写入分配的缓冲区时都要小心,不要超过/覆盖为其分配的内存。