C/C++指针(双重指针)问题

4

距离我上过C和C++课程已经有一段时间了,现在我对C指针很感兴趣(虽然我知道malloc是C的方式,但我将在我的示例中使用new关键字)。我总是记得我的老师强制我们使用指针,她从来不接受数组作业,她向我们证明了用指针而不是数组时汇编语言所需的命令更少。我想继续这个好习惯,但我似乎很难使用指针,特别是双指针。

假设我想创建一个单词库,而不使用C++字符串数据类型,我有一个char类型的双指针。

int main()
{
   string fileName = "file.txt";
   char** wordBank = null;
   int wordCount = countWords(fileName); //somefunction to get word count
}

现在我需要分配一个足够大的内存空间来为整个银行服务,但是我不确定如何做到这一点。我认为应该像这样:

wordBank = new char*[wordCount];

现在我需要为每个单词分配特定的空间大小,但我仍然不确定。

for(int i = 0; i < wordCount; i++)
{
   wordLength = getWordLength(fileName, i); // some function to get word length of each...
   //... word in the bank
   (*wordBank) = new char[wordLength];
}

好的,最后一部分让我有点困惑的是如何通过函数传递双指针。 假设我有一个函数可以操作整个单词,假设我只想传递这个单词,那么在函数调用中我应该传递什么,在函数定义中又应该怎样写?如果我想传递整个银行和一个移动指针的数字,那么在函数调用中我应该传递什么,在函数定义中又应该怎样写?抱歉提了这么多问题,通常来说我会尝试编写短程序自己回答这些问题,但我现在很难让它编译通过。感谢您的回复。


2
我尽量避免混合使用 *[] - motoku
wordBank[i] = new char[wordLength] - angdev
1
我知道你在问题中说你不想这样做,但是如果你正在使用C++(如new关键字所示),那么我非常强烈建议使用std::string。在这种情况下没有不使用它的好理由。它将为您处理所有的内存管理,您不必担心空终止符,并且它的效率不会比自己分配和复制低。你的wordBank数组最好也是一个std::vector<std::string>。同样,它并不会降低效率,但更容易、更安全地使用。 - Tristan Brindle
少的命令并不一定意味着更好的性能。查找“过早优化”。我认为这个概念并不是一个好的实践,恰恰相反。相信我,当你在各处使用newmalloc时,你会花费更多的时间来担心程序出了什么问题,而你真正节省的性能却很少。 - Excelcius
2个回答

8
为了分配银行:
wordBank = malloc(wordCount * sizeof(char *));

分配单词:

char *addWord(char **wordBank, size_t idx, char *word) {
  wordBank[idx] = malloc(strlen(word) + 1);
  // this is how you pass a word
  strcpy(wordBank[idx], word);
  return wordBank[idx];
}

// how you pass the wordBank:
addWord(wordBand, index, someWord);

但是,在汇编语言中有更多的指令并不一定是坏事。在编程中,常数开销通常不是问题。我会使用std :: stringstd :: vector<string>,并将时间花在真正的问题上。至少不用在调试malloc和free、分配和测试NULL指针上浪费时间。


иөһеҗҢдҪҝз”Ёstd::stringе’Ңstd::vector<std::string>...дҪҶеңЁдҪ зҡ„дҫӢеӯҗдёӯпјҢдҪҝз”ЁnewиҖҢдёҚжҳҜmallocдјҡжӣҙеҘҪеҗ§пјҹ - jsantander
也许用C++会更好,但使用new/delete甚至都没有意义 :) - perreal
如果您使用Posix,则wordBank[i] = strdup(word)会稍微简短一些。 - Tristan Brindle
我可以为最后一段额外给一个赞吗? :) - Excelcius
此外,数组和指针访问之间的汇编语言差异往往是简单的算术运算。即使代码需要进行优化,通常也需要更改缓存未命中和/或不可预测的条件分支才能产生明显的差异。最后一段加1。 - Patricia Shanahan

1
我理解为:“我的看法:”
wordBank = new char*[wordCount];

这很好:您正在分配一个由char*元素组成的wordCount数组。
for(int i = 0; i < wordCount; i++)
{
   wordLength = getWordLength(fileName, i); // some function to get word length of each...
   //... word in the bank
   wordBank[i] = new char[wordLength];
}

正如评论中所指出的(@angdev),对于数组中的每个项(char*),我们需要分配内存。

需要注意的一点是,在完成时必须记得释放该内存...并且您应该使用正确的操作进行释放:

  • 如果您使用了malloc() ---> 使用free()
  • 如果您使用了new ---> 使用delete
  • 如果您使用了new [] ---> 使用delete []

最后,如果您需要在函数内修改指针,请使用指向指针的引用:

char *myPointer=0;

fillIt(myPointer);

所以...如果你想让fillIt()实际修改myPointer指向的位置,函数应该是:

void fillIt(char * & p) { ... }

或者您可以定义它为:

void fillIt(char ** p) { ... }

并将其作为调用

char *myPointer=0;

fillIt(&myPointer);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接