1

我有一些函数需要返回一个 const char* (以便大量其他函数最终可以使用它)。

我知道,如果我有如下定义:

const char* Foo(int n)
{
    // Some code
    .
    .
    .
    return "string literal, say";
}

那么就没有问题了。但是我是否正确地说,如果 Foo 必须返回一些只能在运​​行时确定的字符串(取决于参数 n,(其中每个 n 取 [0, 2^31-1] 中的任何值)唯一地确定返回字符串)) 那么我必须使用堆(或返回像 std::string 这样在内部使用堆的对象)?

对于我想要完成的事情,std::string 似乎太重了(至少有两个函数必须传递包裹),并且在 Foo 内分配内存以由调用者释放并不让我觉得这是一种安全的前进方式。我不能(轻松)传递对需要此函数的对象的引用,并不是说我相信无论如何都是可能的,但宏诡计是不可能的。

有没有我还没有考虑过的简单事情?

编辑

感谢所有人的回答,我会选择 std::string (我想以迂回的方式要求确认没有办法向编译器暗示它应该存储一些 char[] 的内容它存储字符串文字的相同位置)。至于“重量级”(我很高兴复制它们并没有我想象的那么浪费)这不是最好的表达方式,也许“不同”会更接近我最初的担忧。

4

5 回答 5

2

如果您的意思是您的函数在n 个已知编译时字符串之一之间进行选择,那么您可以只返回一个 const char * 给其中任何一个。字符串文字在 C 和 C++ 中具有静态存储持续时间,这意味着它们在程序的生命周期内都存在。因此,返回指向 1 的指针是安全的。

const char* choose_string(int n)
{
  switch(n % 4)
  {
    case 0: return "zero";
    case 1: return "one";
    case 2: return "two";
    case 3: return "three";
  }
}

如果您的函数在运行时动态生成一个字符串,那么您必须传入 a(char *buf, int buf_length)并将结果写入其中,或者返回 a std::string

于 2013-08-27T23:50:49.930 回答
2

在 C++ 中,返回 astd::string可能是正确的答案(正如其他几个人已经说过的那样)。

如果您出于某种原因不想使用std::string(例如,如果您使用 C 编程,但您会以这种方式标记问题),则有几个选项可用于从函数“返回”字符串。他们都不漂亮。

  • 如果您返回一个字符串文字,那么您真正返回的是一个指向与该字符串文字关联的数组对象的第一个字符的指针。该对象具有静态存储持续时间(即,它存在于程序的整个执行过程中),因此返回指向它的指针是非常安全的。这显然是不灵活的。
  • 您可以在堆上分配一个数组并返回一个指向它的指针。这让被调用的函数可以确定它需要多长时间,但它会给调用者带来负担,以便在不再需要时释放内存。
  • 您可以返回指向static函数内部定义的数组(的第一个元素)的指针。这是不灵活的,因为最大长度必须在编译时确定。这也意味着对该函数的连续调用将破坏结果。asctime()中定义的函数就是这样做的。(我曾经写过一个函数,它循环遍历数组的静态数组的元素,这样 6 次连续调用不会破坏以前的结果,但第 7 次会破坏。这可能是矫枉过正。)<time.h> <ctime>
  • 您可以要求调用者传递一个指向调用者本身必须分配的数组(的第一个元素)的指针,可能还需要一个单独的参数来指定调用者数组的长度。这需要调用者知道字符串可能有多长,并且可能能够处理没有保留足够空间的错误。

现在你知道了为什么 C++ 提供了像std::string这样的库特性​​来为你处理所有这些东西。

顺便说一句,“可变字符串文字”这个短语没有多大意义。如果某物是文字,则它不是可变的。您的意思可能是“可变字符串”。

于 2013-08-28T00:03:09.000 回答
1

最简单的解决方案可能是返回一个std::string.

如果您想避免使用 std::string,另一种方法是让调用者将char[]缓冲区传递给函数。您可能还想提供一个函数来告诉调用者需要多大的缓冲区,除非上限是静态已知的。

于 2013-08-27T21:34:41.220 回答
1

使用std::string,但如果你真的想要... C 编程中使用的一个常见模式是返回最终结果的大小,分配一个缓冲区,然后调用该函数两次。(我为 C 风格道歉,你想要一个 C 解决方案我给一个 C 解决方案:P)

size_t Foo(int n, char* buff, size_t buffSize)
{
  if (buff)
  {
    // check if buffSize is large enough if so fill
  }
  // calculate final string size and return
  return stringSize;
}

size_t size = Foo(x, NULL, 0); // find the size of the result
char* string = malloc(size); // allocate
Foo(x,string, size); // fill the buffer
于 2013-08-27T21:35:50.750 回答
0

(穿上石棉套装)

考虑只是泄漏内存。

const char* Foo(int n)
{
  static std::unordered_map<int, const char*> cache;
  if (!cache[n])
  {
    // Generate cache[n]
  }
  return cache[n];
}

是的,这会泄漏内存。最多 2^32 个字符串。但是,如果您有实际的字符串文字,那么您将始终在内存中拥有所有2^32 个字符串(并且显然需要 64 位构建 - 仅 \0 就需要 4GB!)

于 2013-08-27T23:01:07.447 回答