将常量字符*缓存为返回类型 在我的C++上读了一点,找到了关于RTI(运行时类型识别)的文章: . 嗯,这是另一个主题:)-然而,我在type_info-类中偶然发现了一个奇怪的说法,即关于::name-方法。它说:“type\u info::namemember函数将const char*返回到一个以null结尾的字符串,该字符串表示该类型的可读名称。指向的内存被缓存,不应直接释放。”

将常量字符*缓存为返回类型 在我的C++上读了一点,找到了关于RTI(运行时类型识别)的文章: . 嗯,这是另一个主题:)-然而,我在type_info-类中偶然发现了一个奇怪的说法,即关于::name-方法。它说:“type\u info::namemember函数将const char*返回到一个以null结尾的字符串,该字符串表示该类型的可读名称。指向的内存被缓存,不应直接释放。”,c++,char,return-value,C++,Char,Return Value,你自己怎么能实现这样的事情!?我以前经常遇到这个问题,因为我不想为调用者创建一个新的char-数组来删除,所以到目前为止我一直坚持使用std::string 因此,为了简单起见,假设我想创建一个返回“Hello World!”的方法,让我们调用它 const char *getHelloString() const; 就我个人而言,我会这样做(伪): 。。但这意味着调用方应该对我的返回指针执行delete[]:( 提前Thx这个怎么样: const char *getHelloString()

你自己怎么能实现这样的事情!?我以前经常遇到这个问题,因为我不想为调用者创建一个新的
char
-数组来删除,所以到目前为止我一直坚持使用
std::string

因此,为了简单起见,假设我想创建一个返回
“Hello World!”
的方法,让我们调用它

const char *getHelloString() const;
就我个人而言,我会这样做(伪):

。。但这意味着调用方应该对我的返回指针执行
delete[]
:(

提前Thx

这个怎么样:

const char *getHelloString() const
{
    return "HelloWorld!";
}

直接返回文本意味着编译器在静态存储中为字符串分配空间,并且在整个程序期间都可用。

我认为,因为他们知道这些字符串的数量有限,所以他们只会永远保留它们。在某些情况下,您可以这样做,但是一般来说,std::string会更好


他们还可以查找新的调用,查看是否已生成该字符串并返回相同的指针。同样,根据您正在执行的操作,这可能对您也很有用。

这可能是使用静态缓冲区完成的:

const char* GetHelloString()
{
    static char buffer[256] = { 0 };
    strcpy( buffer, "Hello World!" );
    return buffer;
}

这个缓冲区就像一个只能通过这个函数访问的全局变量。

好吧,如果我们只讨论一个函数,你总是希望返回相同的值。这很简单

const char * foo() 
{
   static char[] return_val= "HelloWorld!";
   return return_val;
}

棘手的一点是,当你开始做缓存的结果,然后你必须考虑线程,或者当你的缓存失效,并试图在线程本地存储中存储东西。但是如果它只是一个一次性输出,立即复制,这就行了。 或者,如果没有固定大小,则必须使用任意大小的静态缓冲区,最终可能会有太大的缓冲区,或者使用托管类,例如

std::string

const char * foo() 
{
   static std::string output;
   DoCalculation(output);
   return output.c_str();
}
还有函数签名

const char *getHelloString() const;
仅适用于成员函数。
在这个时候,你不需要处理静态函数局部变量,只需要使用一个成员变量。

你不能依赖GC;这是C++。这意味着你必须保持内存可用,直到程序终止。你根本不知道什么时候安全删除[]。因此,如果你想构造并返回一个常量char*,简单的new[]它并返回它。接受不可避免的泄漏。

为什么返回类型必须是
const
?不要将该方法视为get方法,而应将其视为create方法。我见过很多API要求您删除创建操作符/方法返回的内容。请确保您在文档中注意到这一点

/* create a hello string
 * must be deleted after use
 */
char *createHelloString() const
{
  char *returnVal = new char[13];
  strcpy("HelloWorld!", returnVal);

  return returnVal
}

当我需要这种功能时,我经常做的是在类中有一个char*指针——初始化为null——并在需要时分配

即:


这样做可以:

const char *myfunction() {
    static char *str = NULL; /* this only happens once */
    delete [] str; /* delete previous cached version */
    str = new char[strlen("whatever") + 1]; /* allocate space for the string and it's NUL terminator */
    strcpy(str, "whatever");
    return str;
}

编辑:我想到了一个很好的替代方法,那就是返回boost::shared_指针。这样,调用者可以保留它,只要他们愿意,而且他们不必担心显式删除它。这是一个公平的折衷办法。

在实现分配一块内存和内存的函数时要小心然后期望调用者释放它,就像您在OP中所做的那样:

const char *getHelloString() const
{
  char *returnVal = new char[13];
  strcpy("HelloWorld!", returnVal);

  return returnVal
}
这样做就是将内存的所有权转移给调用者。如果从其他函数调用此代码:

int main()
{
  char * str = getHelloString();
  delete str;
  return 0;
}
…转移内存所有权的语义不清楚,这就造成了更容易出现错误和内存泄漏的情况


另外,至少在Windows下,如果这两个函数位于两个不同的模块中,则可能会损坏堆。特别是,如果main()位于hello.exe中,在VC9中编译,以及getHelloString()中是在utility.dll中,在VC6中编译,当您删除内存时,您将损坏堆。这是因为VC6和VC9都使用自己的堆,并且它们不是同一堆,因此您从一个堆分配,从另一个堆取消分配。

警告返回字符串的生存期的建议是合理的建议。您应该在管理返回指针的生命周期时,要小心识别你的职责。但是,实践是相当安全的,但是如果指向的变量将超过调用返回函数的函数。例如,考虑由<代码> CyScript()返回的const char指针。作为类的一种方法
std::string
。这将返回一个指向由string对象管理的内存的指针,只要string对象没有被删除或重新分配其内部内存,该指针就保证有效


<> > <代码> STD::Type OnngIs<代码>类,它是C++标准的一部分,其命名空间意味着。从NoMe()/Cuffe返回的内存实际上指向编译时的编译器和链接器创建的静态内存,是运行时类型标识(RTI)的一部分。系统。因为它引用了代码空间中的符号,所以不应该尝试删除它。

我喜欢所有关于如何静态分配字符串的答案,但这并不一定适用于所有实现,尤其是原始海报链接到其文档的实现。在这种情况下,它似乎
const char *getHelloString() const
{
  char *returnVal = new char[13];
  strcpy("HelloWorld!", returnVal);

  return returnVal
}
int main()
{
  char * str = getHelloString();
  delete str;
  return 0;
}
#include <cstdio>
#include <typeinfo>
#include <vector>    
int main(int argc, char* argv[]) {
    std::vector<int> v;
    const type_info& ti = typeid(v);
    const char* n = ti.name();
    printf("%s\n", n);
    return 0;
}
0:000> ?? n
char * 0x00000000`00857290
 "class std::vector<int,class std::allocator<int> >"
0:000> ln 0x00000000`00857290
0:000>
0:000> !heap -x 0x00000000`00857290
Entry             User              Heap              Segment               Size  PrevSize  Unused    Flags
-------------------------------------------------------------------------------------------------------------
0000000000857280  0000000000857290  0000000000850000  0000000000850000        70        40        3e  busy extra fill 
struct __type_info_node {
    void *memPtr;
    __type_info_node* next;
};

extern __type_info_node __type_info_root_node;
...
_CRTIMP_PURE const char* __CLR_OR_THIS_CALL name(__type_info_node* __ptype_info_node = &__type_info_root_node) const;
class ICanReturnConstChars
{
    std::stack<char*> cached_strings
    public:
    const char* yeahGiveItToMe(){
        char* newmem = new char[something];
        //write something to newmem
        cached_strings.push_back(newmem);
        return newmem;
    }
    ~ICanReturnConstChars(){
        while(!cached_strings.empty()){
            delete [] cached_strings.back()
            cached_strings.pop_back()
        }
    }
};