MST

星途 面试题库

面试题:C++字符串常量与const char* 及string的内存关联与转换

在C++中,const char* 可以指向字符串常量,而string类也常用于处理字符串。请详细说明字符串常量与const char* 以及string之间在内存分配上的关系,如何实现它们之间的转换,在转换过程中内存是如何管理的,并分析可能出现的内存问题及解决方案。
12.8万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

内存分配关系

  1. 字符串常量:字符串常量存储在程序的只读数据段。例如 "Hello" 这样的字符串常量,在程序运行期间其值不能被修改,占用一段连续的内存空间。
  2. const char*const char* 是一个指针,它可以指向字符串常量。指针本身存储在栈上(如果是局部变量),而它指向的字符串常量在只读数据段。例如 const char* str = "Hello";str 在栈上,"Hello" 在只读数据段。
  3. stringstring 类对象存储在栈上(如果是局部变量),它内部有一个指向动态分配内存的指针,该动态分配的内存用于存储字符串内容,位于堆上。例如 string s = "Hello";s 本身在栈上,s 内部指向的存储 "Hello" 的内存位于堆上。

转换方式及内存管理

  1. const char*string
    • 可以使用 string 的构造函数。例如:
    const char* cstr = "Hello";
    string s(cstr);
    
    • 内存管理:string 类会在堆上分配足够的空间来存储 cstr 指向的字符串内容,然后复制字符串。当 string 对象生命周期结束时,string 类的析构函数会释放堆上分配的内存。
  2. stringconst char*
    • 可以使用 string 类的 c_str() 成员函数。例如:
    string s = "Hello";
    const char* cstr = s.c_str();
    
    • 内存管理:c_str() 返回的指针指向 string 对象内部的字符数组(该数组以 '\0' 结尾),但 string 类对象负责管理这块内存。调用者不应尝试释放该指针指向的内存。而且,只要 string 对象的内容不发生改变,c_str() 返回的指针就保持有效。如果 string 对象发生改变(例如插入、删除字符),c_str() 返回的指针可能不再有效。
  3. 字符串常量转 string
    • 同样使用 string 的构造函数。例如:
    string s = "Hello";
    
    • 内存管理:string 类在堆上分配内存来存储字符串常量的内容,并复制字符串。当 string 对象销毁时,释放堆上的内存。
  4. 字符串常量转 const char*
    • 直接赋值即可。例如:
    const char* cstr = "Hello";
    
    • 内存管理:cstr 指向只读数据段中的字符串常量,不需要额外的内存分配或释放操作,因为字符串常量的生命周期与程序相同。

可能出现的内存问题及解决方案

  1. 内存泄漏(const char*string
    • 问题:如果在构造 string 对象后,没有正确释放相关资源(例如在异常情况下),可能导致内存泄漏。
    • 解决方案:使用智能指针或确保 string 对象在作用域结束时正常析构。例如,在 try - catch 块中正确处理异常,避免资源泄漏。
  2. 悬空指针(stringconst char*
    • 问题:如果 string 对象被销毁,而其 c_str() 返回的指针仍在使用,就会产生悬空指针。
    • 解决方案:确保在 string 对象的生命周期内使用 c_str() 返回的指针,或者在需要长期使用字符串内容时,将其复制到新的 const char* 指向的独立分配的内存中(例如使用 strdup 函数,在 C++ 中可以自己实现复制逻辑)。
  3. 缓冲区溢出
    • 问题:当从 const char*string 转换或反向转换时,如果操作不当,可能导致缓冲区溢出。例如,在手动复制 const char* 内容到 string 预留的缓冲区时,如果 const char* 内容过长就会溢出。
    • 解决方案:使用安全的字符串操作函数,string 类本身在处理字符串复制等操作时相对安全,但在手动操作时要注意边界检查。