我有一个接收char *
参数的函数:
Foo::Foo (char * arg0) {
....
}
在原始示例中,char[]
用于传递此值...
char bar[] = "Bar";
Instance.foo (bar);
......工作正常。
但是,我发现我可以传递一个字符串文字,强制转换为char *
,而不会给编译器发出任何警告。
Instance.Foo ((char *) "Bar");
然而,从我的阅读中,似乎应该避免 - 指向的内存值可能会改变。
上述陈述是否属实(“应该避免这种情况”)或在这种情况下是否合适?
编辑 - 进一步研究this article,很好地解决了我的问题......
答案 0 :(得分:8)
是的,避免这样做。现在,如果您的函数使用const char *
,则使用字符串文字调用它没有任何问题。
C ++编译器仅支持字符串文字到char *
,仅出于向后兼容性原因,写入字符串文字会导致未定义的行为。
当你执行char bar[] = "Bar";
时,你正在做一些根本不同的事情(即初始化一个包含你可以自由修改的值{'B', 'a', 'r', '\0'}
的4个字符的数组),而不是char bar* = "Bar";
(你在哪里创建一个非const
指向你不能修改的4字节字符串。
在我看来,您永远不应该将字符串文字直接转换为char*
,而是将其放入const char*
然后(如果您正在与遗留API进行通信)明确const_cast<char*>
const
离开时,评论说您正在与遗留API进行对话,该API保证不会更改char
。这样做的好处是,您可以在升级API时搜索程序中的const_cast
,或者您想要找到涉及写入char*
的分段错误的来源。
甚至可以使用const char*
版本中的const_cast
封装旧版API。
绝对最糟糕的情况是会有一堆char*
徘徊,其中一些是可写的,另一些来自字符串文字。
答案 1 :(得分:1)
应该几乎不惜一切代价避免这种情况,只有当你必须与破旧的遗传API接口时才会这样做,并且只有你看过他们的源代码并确保他们没有写入字符串。
保持安全,并在传递之前用strcpy
复制字符串。
究竟什么是邪恶的?写入字符串文字是未定义的行为。