C++常量字符串工作原理及类实例构造析构异常输出问题咨询
C++常量字符串工作原理与代码崩溃问题解析
一、常量字符串(字符串字面量)的工作原理
当你在代码里写"Jack"、"Katy"这种字符串字面量时,背后的逻辑是这样的:
- 编译器会把这些字符串存储在程序的只读数据段(通常叫
.rodata)里,这部分内存在程序运行时是只读的,不能被修改。 - 字符串字面量的实际类型是
const char[N](N是字符串的字符数+1,因为末尾会自动加一个'\0'作为终止符)。为了兼容C语言的旧代码,C允许把它隐式转换成char*,但这是不推荐的——C11及以后标准更严格,直接用char*指向字符串字面量会触发警告,正确的做法是用const char*。 - 这些字符串字面量的生命周期是全局的:从程序启动时就加载到内存,直到程序结束才会被释放。
二、你的代码崩溃的核心原因
看你的temp类代码,问题出在未初始化的指针name:
- 类里的
char* name只是声明了一个指针,但没有给它分配有效的内存地址——它的初始值是随机的“野指针”,指向内存里的某个未知区域(可能是程序的其他数据区,甚至是只读区域)。 - 构造函数里调用
strcpy(name, temp_name),是把字符串字面量的内容复制到name指向的随机内存位置。这属于未定义行为:要么直接触发内存访问错误导致崩溃(就是你看到的Cr...),要么悄悄覆盖程序的其他数据,导致后续出现奇怪的bug。
三、修复方案
方案1:手动管理动态内存(C风格)
如果一定要用char*,需要在构造函数里为name分配足够的内存,并且在析构函数里释放:
#include <cstring> #include <iostream> class temp { private: char* name; public: // 参数改成const char*,符合字符串字面量的const属性 temp(const char* temp_name) { // 分配内存:长度是字符串长度+1(存储终止符'\0') name = new char[strlen(temp_name) + 1]; strcpy(name, temp_name); std::cout << "Created " << name << std::endl; } ~temp() { std::cout << "Destroyed " << name << std::endl; delete[] name; // 记得用delete[]释放数组类型的动态内存 } // 额外提示:如果需要拷贝对象,必须实现拷贝构造和赋值运算符(Rule of Three) // 否则浅拷贝会导致重复释放内存崩溃,这里暂时省略,你可以自行补充 }; int main() { // C++里声明对象不需要重复写class,直接写类名即可 temp person1("Jack"); temp haha("Katy"); return 0; }
方案2:使用std::string(C++推荐方案)
C++标准库提供的std::string会自动帮你管理内存,完全避免手动分配释放的麻烦,代码更简洁安全:
#include <string> #include <iostream> class temp { private: std::string name; public: // 用初始化列表直接初始化name,比在构造函数里赋值更高效 temp(const std::string& temp_name) : name(temp_name) { std::cout << "Created " << name << std::endl; } ~temp() { std::cout << "Destroyed " << name << std::endl; } // std::string自动支持拷贝、赋值等操作,不需要手动实现 }; int main() { temp person1("Jack"); temp haha("Katy"); return 0; }
额外注意点
- 字符串字面量是只读的,所以构造函数的参数最好用
const char*或者const std::string&,避免编译器警告。 - 永远不要对未初始化的指针进行内存操作,一定要确保指针指向有效的内存区域(要么动态分配,要么指向已存在的合法数组)。
内容的提问来源于stack exchange,提问作者Nagato
相关产品推荐
相关产品推荐

