Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;:返回C字符串的最快方法_C++_C_Performance - Fatal编程技术网

C++ C++;:返回C字符串的最快方法

C++ C++;:返回C字符串的最快方法,c++,c,performance,C++,C,Performance,我有一个简单的函数,它接受一个字符并返回一个字符串,在C语言中看起来像 char* get_string(char c) { switch(c) { case 'A': return "some string"; Case 'B': return "some other string"; ... 它工作正常,但我希望我的代码在C++中工作,C++编译器抛出一个“字符串常数”到“char *”的“不可转换的转换”。我理解这个警告,但我不确定100%是实现函数的最佳方法,所以它

我有一个简单的函数,它接受一个字符并返回一个字符串,在C语言中看起来像

char* get_string(char c) {
  switch(c) {
    case 'A': return "some string";
    Case 'B': return "some other string";
...

它工作正常,但我希望我的代码在C++中工作,C++编译器抛出一个“字符串常数”到“char *”的“不可转换的转换”。我理解这个警告,但我不确定100%是实现函数的最佳方法,所以它将在C和C++上运行得很快。这个函数经常被调用,这是一个重要的瓶颈,所以它必须很快。我最好的尝试是

char* get_string(char c) {
  char* str = (char*)malloc(50);
  switch(c) {
    case 'A':
      sprintf(str, "some string");
      return str;
    Case 'B':
      sprintf(str, "some other string");
      return str;
...

返回一个
const char*
而不是
char*
。此上下文中的
const
表示“此指针指向常量指针对象”-换句话说,调用方无法修改返回的字符串。这允许编译器将字符串放在某个内存位置,以便
get\u string()
函数只返回这些字符串的地址。如果调用者需要修改返回的字符串,他们可以分配自己的缓冲区并复制它(最好通过
std::string


使原始函数返回
const char*
而不是
char*
。问题是字符串文本是常量。新编译器不允许将它们直接强制转换为非常量类型。

如果您返回的是常量字符串(本例中是常量字符串),则返回值应为
const char*
。如果需要返回可变字符串,通常有三种方法:

强制调用方事先分配字符串

int get_string (char c, char* outstr, size_t outstr_len) 
{
   // Write the output into outstr using strcpy or similar
   // and return an error code if outstr_len is smaller than
   // the space required to store the string
}
这是C语言中最惯用的语言,但调用方需要做的工作最多

代表调用方分配字符串

char* get_string (char c) 
{ 
   char* str = malloc(/* however big */);
   // ...
   return str;
}
请注意,此方法相对较慢,您需要记录调用者有责任释放返回的字符串,并且应该使用
free
(而不是
delete[]
)释放该字符串。您可以在此处使用
new[]
delete[]
而不是
malloc
free
,但我认为您这样做的唯一原因是与C代码交互操作

分配一个静态缓冲区

char* get_string (char c) 
{ 
   static char* str[/* however big */];
   // ...
   return str;
}
在这里,您必须记录返回的字符串保证有多大,并且调用方不能释放它。这里的主要缺点是对
get_string
的后续调用将破坏先前返回的字符串


Ed:Hm,markdown似乎不喜欢混合代码和列表

使用
常量字符
。但是,如果此函数确实是一个瓶颈,则应该使用静态分配的数组,而不是switch语句。如果您可以简单地执行以下操作,则可以将响应时间从O(n)提高到O(1):

const char* MyStrings[100];

... initialize MyStrings ...

const char* get_string(char c) {
    return MyStrings[c-'A'];
}

您可以结合一些已经给出的解决方案,使其更快,但在某个时候,您将遇到收益递减的问题,在这种情况下,额外的努力可能不值得获得收益

我将使用固定字符串返回一个
const char*
,并从一个静态数组中执行,假设您可以保证源范围是连续的(例如
'a'
'C'

使用静态常量字符数组意味着在不需要可写副本的情况下,成本最低。创建此数组的成本很可能是在编译时而不是运行时。如果调用者确实想要一个可写副本,则由他们使用以下方法来实现:

char *x = strdup ( get_string ('A'));
const char * get_string (char c) {
    static const char *arr[] = {
        "some string",              // A
        "some other string"         // B
    };                              // any other value is undefined behaviour.
    return arr[c-'A'];
}
(是的,我知道strdup不是ISO标准,但无论如何它都是)。同样对于原始速度,您可以放弃错误检查,并假设调用者不会传递合同中的无效值

比如:

char *x = strdup ( get_string ('A'));
const char * get_string (char c) {
    static const char *arr[] = {
        "some string",              // A
        "some other string"         // B
    };                              // any other value is undefined behaviour.
    return arr[c-'A'];
}

这一点很重要,不要假设这个(或任何其他解决方案)将是基于您认为您知道的最快的解决方案。优化的咒语是“测量,不猜测”(和在类似生产环境中的测量)。< /P>解决方案:在C++中停止使用C字符串:PI实际上根本不使用C++,但是我希望我的代码是C++兼容的。谢谢,正是我想要的。@保罗,确保“接受”他的答案,这样我们就知道这个问题是关闭的。上面的第二个示例使调用方负责释放malloc的内存。@Anders,只有当您不将其作为函数契约的一部分时,它才是不安全的。该函数的输入可能仅从已验证的数据输入中收集(例如仅包含a和B的下拉列表)。在这种情况下,抛弃所有错误检查是完全可以接受的,只要API指定它只与有效参数一起工作。在执行函数时,避免对输入进行假设通常是非常好的。如果一个函数有(char c)作为参数,它意味着(对于函数的用户)任何字符都可以被传递(当某一天该函数在别处使用时-因此我对不安全的评论。如果你检查'c'参数的范围,它仍然是O(1).-1 for“可以改善从O(n)到O(1)的响应时间)*-假设
switch
语句必须是O(n)是错误的-编译器通常会分析大小写值并选择查找机制-可能是O(n)、O(log2N)(例如,编译器对大小写进行排序,然后进行二进制搜索)或O(1)。如果大小写值密集(即接近连续),则可以合理地预期为O(1)大量且容易崩溃的未检查数组查找是一个坏主意,除非实际分析表明——尽管有上述情况——它恰好在您的特定情况下产生了有用的加速。字符串文本在C中不是
const char[]
类型,无论编译器多么新(尽管它们一直是不可修改的)。这些字符串文字是/ready/a“const char*”。不需要将它们绑定到变量名,也不需要强制它们是静态的,这很可能已经是这样了。@Arafangion,实际上它们在C.C99中不是const char