const char* 与 char* (C++)
Posted
技术标签:
【中文标题】const char* 与 char* (C++)【英文标题】:const char* vs char* (C++) 【发布时间】:2011-06-01 22:39:36 【问题描述】:对于以下程序:
int DivZero(int, int, int);
int main()
try
cout << DivZero(1,0,2) << endl;
catch(char* e)
cout << "Exception is thrown!" << endl;
cout << e << endl;
return 1;
return 0;
int DivZero(int a, int b, int c)
if( a <= 0 || b <= 0 || c <= 0)
throw "All parameters must be greater than 0.";
return b/c + a;
使用 char* e 会给出
在抛出一个之后调用终止 'char const*' 的实例
根据C++ Exception Handling,解决方法是改用const char*。
来自function (const char *) vs. function (char *)的进一步阅读说
“字符串”的类型是
char*', not
const char*'(我认为这是一个 C 讨论...)
Stack Overflow char* vs const char* as a parameter 上的附加阅读告诉我区别。但他们都没有解决我的问题:
-
char* 和 string* 似乎都对字符数有限制。我说的对吗?
将关键字 const 添加到 char* 如何消除该限制?我认为 const 的唯一目的是设置一个表示“不可修改”的标志。我理解 const char* e 的意思是“指向不可修改的 char 类型的指针”。
解决该错误的方法是使用 const char* e。
即使是 const string* e 也不起作用。 (只是为了测试......)
谁能解释一下?谢谢!
顺便说一句,我在 Ubuntu 上,由 GCC 编译,在 Eclipse 上。
【问题讨论】:
【参考方案1】:您链接到的关于“字符串”的电子邮件是错误的(并且令人困惑)。
基本上:
char*
是一个指向无限字符数组的指针。传统上我们认为这样的数组是一个 C 字符串,如果它包含一组有效字符,后跟一个\0
。数组的大小没有限制。
const char*
是一个指向不可变字符的无限数组的指针。
string*
是指向std::string
对象的指针,完全不同。这是一个封装字符串的智能对象。使用std::string
代替 C 字符串可以让你的生活更轻松,即使它们有一些粗糙的边缘和很多讨厌的陷阱;它们非常值得研究,但与问题无关。
"String"
是一个特殊的表达式,它返回一个指向特定 C 字符串的 const char*
(注意:这实际上不是真的,但它是一种简化,可以让我简洁地回答这个问题)。
char*
可以自动转换为const char*
,反之则不行。请注意,旧的 C++ 编译器对类型规则有一个特殊例外,允许您这样做:
char* s = "String";
...不产生类型错误;这是为了 C 兼容性。现代 C++ 编译器不会让你这样做(比如最近的 gccs)。他们需要这个:
const char* s = "String";
所以。这里的问题是你有:
throw "All parameters must be greater than 0.";
...但是你试图抓住它:
catch(char* e)
这不起作用,因为 throw 是在抛出一个 const char*
,它不能被强制转换为 catch 中指定的类型,所以它不会被捕获。
这就是为什么将 catch 更改为:
catch (const char* e)
...让它工作。
【讨论】:
+1,但我所知道的每个编译器(包括最近的 GCC)都可以让你在char* s = "String";
上运行而不会出错。另一方面,有些人可能会发出警告... (Demo)
很好解释。我希望我可以标记每个人,但我不能。他比你先回答。没关系,我猜。你的解释很有帮助。我很喜欢。谢谢,大卫。实际上,我在 const.... 上找到了更多名为“const-correctness”的 wiki 文章。 :]
@ildjarn +1 感谢您的精彩评论和演示。 :]
@JohnWong 很高兴能帮上忙(甜甜的声望点也不错,muhahaha)。 const 正确性非常值得学习; C++ 是一种非常挑剔且极其微妙的语言,正确地获得 const 的正确性有时可能会让人头疼,但在避免您以后失足时会非常有帮助。 C++ 不是我最喜欢的语言...【参考方案2】:
你为什么还要扔和接绳子?
您应该抛出和捕获异常,例如std::runtime_error
您的问题的答案是,每当您在代码中的引号中插入一个字符串时,它都会返回一个以 null 结尾的 const char*
您的代码无法按上述方式运行的原因是它的类型错误,因此 catch 并没有捕捉到您抛出的内容。你正在抛出一个 const char*。
char 数组中超出堆栈/堆大小的字符数没有限制。如果您指的是您发布的示例,则该人创建了一个固定大小的数组,因此它们受到限制。
【讨论】:
@Salgar 这是来自数据结构基础 (2ed) 一书的示例代码。所以如果我插入 int [] 它将返回为 const int* ???? (使用 const 关键字)? 同意,从 std::exception 派生所有异常。抛出基本类型会导致麻烦。确保所有内容都源自 std::exception 可以确保catch(std::exception e)
将捕获所有内容。您想为最极端的情况(例如 DLL 边界)保留 catch(...)
。经常抛出基本类型会导致经常需要catch(...)
。使用throw std::runtime_error("All parameters must be greater than 0.");
是的,让您确保 catch(const std::exception& e) 将捕获所有内容。
@JongWong 没有,代码“foo”的类型是const char*,int[]的类型是int[],int*的类型是int*
我很确定字符串文字的类型为const char[N]
,N
是字符串长度+`(对于'\0'
),而不是const char*
,它只是衰减到那个。 以上是关于const char* 与 char* (C++)的主要内容,如果未能解决你的问题,请参考以下文章
在 C++ 中将 const char * 与字符串连接的最干净的方法是啥?