C++指针问题
C++ Pointer question
我是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"
}
这不是与人们刚才所说的相反吗?
您在内存中分配了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 *
有很大不同,主要是因为您不必担心它们的分配/释放。它们在内存中的处理通常也非常不同,但这取决于编译器的实现。
你说得对。
-
您需要遍历该数组的每个元素,并为每个元素分配一个字符缓冲区。
-
然后,稍后,您需要遍历该数组的每个元素,然后再次释放内存。
为什么你想在C++中对此感到困惑,这是任何人的猜测。
std::vector<std::string> myStrings(20)
出了什么问题?
它将为二十个字符指针分配空间。
它们不会被初始化,所以典型的用法看起来像
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]);
你是对的-第一种方法可能会引入内存泄漏问题和动态分配的开销,以及更多的读取。我认为第二种方法通常更可取,除非它浪费了太多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.
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];
首先,这在C++中几乎不适用。C++中的正规等价物类似于:std::vector<std::string> something;
在C中,主要的区别在于可以将每个字符串与其他字符串分开分配。使用char something[M][N]
,您总是为每个字符串分配完全相同数量的字符串和相同的空间。这将经常浪费空间(当字符串比您腾出的空间更短时(,并且不允许您处理比最初腾出的空间更多或更长的字符串。
char *something[20]
让您可以更有效地处理较长/较短的字符串,但仍然只为20个字符串腾出空间。
下一步(如果你觉得有冒险精神(是使用类似的东西:
char **something;
并且分别分配字符串,和也动态地为指针分配空间,所以如果你得到20个以上的字符串,你也可以处理它。
然而,我要重复一遍,对于大多数实用目的,这仅限于C。在C++中,标准库已经有了适用于此类情况的数据结构。
C++有指针,因为C有指针。
我们为什么要使用指针?
-
跟踪动态分配的内存C中的内存分配函数(
malloc
、calloc
、realloc
(和C++中的new
运算符都返回指针值。 -
模拟传递引用语义(仅限C(在C中,所有函数参数都是通过值传递的;形式参数和实际参数是不同的对象,修改形式参数不会影响实际参数。我们通过向函数传递指针来解决这个问题。C++引入了引用类型,它们具有相同的目的,但比使用指针更干净、更安全。
-
构建动态、自引用的数据结构
struct
不能包含其自身的实例,但它可以包含指向实例的指针。例如,下面的代码
为一个简单的链表节点创建了一个数据类型;CCD_ 16成员明确地指向列表中的下一个元素。请注意,在C++中,用于堆栈、队列和向量的STL容器都在后台使用指针,将您与记账隔离开来。struct node { data_t data; struct node *next; };
实际上,还有几十个其他地方会出现指针,但这些都是你使用它们的主要原因。
指针数组可以用于存储不同长度的字符串,方法是为每个字符串分配足够的内存,而不是依赖于某个最大大小(最终会超过该大小,导致缓冲区溢出错误,并且在任何情况下都会导致内部内存碎片(。当然,在C++中,您会使用string
数据类型(它将所有指针和内存管理隐藏在类API后面(,而不是指向char
的指针,但有人决定从低级细节而不是全局图开始,这会让您感到困惑。
我不是确定为什么我需要像char这样的指针*与木炭相反的东西某物[20][100]。我意识到第二种方法意味着100将为分配内存块数组中的每个元素,但是第一种方法不是介绍内存泄漏问题。
如果您只在本地引用缓冲区,那么第二种方法就足够了。
当您将数组名称传递给另一个函数时,就会出现问题。当您将char something[10]
传递给另一个函数时,实际上您传递的是char* something
,因为数组长度与行程不一致。
对于多维数组,您可以声明一个函数,该函数在除一个方向外的所有方向上接收一个确定长度的数组,例如foo(char* something[10])
。
那么,为什么要使用第一种形式而不是第二种形式呢?我能想到几个原因:
- 您不希望有整个缓冲区必须驻留在连续内存中的限制
- 在编译时,您不知道是否需要每个缓冲区,或者每个缓冲区的长度是否需要相同的大小,并且您希望在运行时能够灵活地确定这一点
- 这是一个函数声明
char*something[20]
假设这是32Bit,则在堆栈上分配80字节的数据。每个指针地址4个字节,总共20个指针=4 x 20=80个字节。
指针都未初始化,因此需要编写额外的代码来分配/释放用于执行此操作的缓冲区。
大致看起来像:
[0][4字节未初始化的数据,用于保存指针/内存地址…][1] [4字节…]。。。[19]
烧焦某物[20][100]
在堆栈上分配2000个字节。每个东西100个字节,20多岁的人总共=100 x 20=2000个字节。
[0][100字节可容纳字符][1] [100字节可容纳字符]。。。[19]
char*的内存开销较小,但您必须管理内存。char[][]方法有更大的内存开销,但没有额外的内存管理。
无论哪种方法,在写入分配的缓冲区时都必须小心,不要超过/覆盖为其分配的内存。
- 关于 c++ 函数中指针赋值的简单问题
- 链表指针问题
- C++ 关于指针取消引用的技术问题
- C++中的指针和常量问题不大
- 包含矢量指针的结构的内存释放问题
- 指针问题:从不兼容的类型"int"分配给"int *"
- 将字节数组转换为带有字节序问题的指针
- 关于如何使用指向主窗口的指针的 QT 问题
- 当成员值从指针更改为非指针时,C++常量问题
- 为什么循环会导致指针出现问题?
- 使用指针计算堆栈问题的大 O 表示法
- 构造函数 (C++) 中的 char 指针参数存在问题
- 指向包含对齐 C 结构C++类的 C 指针的对齐问题
- 涉及指针和手动实现的矩阵类的问题
- 从基指针到派生的强制转换问题
- 迭代器的指针操作问题
- 64 位迁移问题:指针更改
- C++模板使用问题指针
- 跳到C++第13章练习问题4-指针
- 用std::pair数组初始化std::map问题(指针错误?)