问题描述
我喜欢了解赞成和反对有和没有这样的演员表的经历。在包括Stack Overflow在内的多个地方,我可以看到 const char *
强制转换被认为是一个坏主意,但我不确定为什么吗?
I like to know pro's and con's for having and not-having such cast. At several places including here on Stack Overflow I can see that the const char*
cast is considered bad idea but I am not sure why?
缺少(const char *)
并强制始终使用 c_str()
强制转换编写通用例程和模板时会遇到一些问题。
Lack of the (const char*)
and forcing to always use c_str()
cast creates some problems when writing generic routines and templates.
void CheckStr(const char* s)
{
}
int main()
{
std::string s = "Hello World!";
// all below will not compile with
// Error: No suitable conversion function from "std::string" to "const char *" exists!
//CheckStr(s);
//CheckStr((const char*)s);
// strlen(s);
// the only way that works
CheckStr(s.c_str());
size_t n = strlen(s.c_str());
return 0;
}
例如,如果我有大量接受 const char *
作为输入,我希望每次必须使用<$时都可以使用 std :: string
c $ c> c_str()。但是以这种方式,模板函数不能同时用于 std :: string
和 const char *
努力。
For example, if I have a large number of text processing functions that accept const char*
as input and I want to be able to use std::string
each time I have to use c_str()
. But in this way a template function can't be used for both std::string
and const char*
without additional efforts.
作为一个问题,我可以看到一些运算符重载问题,但是可以解决。
As a problem I can see some operator overloading issues but these are possible to solve.
例如,正如[eerorika]指出的那样,通过允许将隐式强制转换为指针,我们允许将非自愿的字符串类包含在布尔表达式中。但是我们可以通过删除bool运算符轻松解决此问题。更进一步,可以强制强制转换运算符是显式的:
For example, as [eerorika] pointed, with allowing implicit cast to pointer we are allowing involuntary the string class to be involved in boolean expressions. But we can easily solve this with deleting the bool operator. Even further, the cast operator can be forced to be explicit:
class String
{
public:
String() {}
String(const char* s) { m_str = s; }
const char* str() const { return m_str.c_str(); }
char* str() { return &m_str[0]; }
char operator[](int pos) const { return m_str[pos]; }
char& operator[](int pos) { return m_str[pos]; }
explicit operator const char*() const { return str(); } // cast operator
operator bool() const = delete;
protected:
std::string m_str;
};
int main()
{
String s = "Hello";
string s2 = "Hello";
if(s) // will not compile: it is a deleted function
{
cout << "Bool is allowed " << endl;
}
CheckStr((const char*)s);
return 0;
}
推荐答案
Con:隐式转换通常具有令人惊讶的行为
Con: Implicit conversions often have behaviour that is surprising to the programmer.
例如,您对以下程序会有什么期望?
For example, what would you expect from following program?
std::string some_string = "";
if (some_string)
std::cout << "true";
else
std::cout << "false";
程序是否格式错误,因为 std :: string
是否没有转换为 bool
?结果应该取决于字符串的内容吗?
Should the program be ill-formed because std::string
is has no conversion to bool
? Should the result depend on the content of the string? Would most programmers have the same expectation?
使用当前的 std :: string
,以上内容将是不正确的-之所以成立是因为没有这种转换。很好无论程序员期望什么,他们在尝试编译时都会发现误解。
With the current std::string
, the above would be ill-formed because there is no such conversion. This is good. Whatever the programmer expected, they'll find out their misunderstanding when they attempt to compile.
如果 std :: string
进行了指针转换,那么还存在一个转换序列,通过转换为指针进行布尔转换。上面的程序格式正确。并且程序将打印 true
而不考虑字符串的内容,因为 c_str
永远不会为空。如果程序员反而希望空字符串为假,该怎么办?如果他们既不想使用任何行为,又偶然在其中使用了字符串,该怎么办?
If std::string
had a conversion to a pointer, then there would also be a conversion sequence to bool through the conversion to pointer. The above program would be well-formed. And the program would print true
regardless of the content of the string, since c_str
is never null. What if programmer instead expected that empty string would be false? What if they never intended either behaviour, but used a string there by accident?
以下程序如何?
std::string some_string = "";
std::cout << some_string + 42;
您是否希望程序格式错误,因为对于字符串和 int
?
Would you expect the program to be ill-formed because there is no such operator for string and int
?
如果隐式转换为 char *
,
// all below will not compile with
strlen(s);
这实际上是一件好事。大多数情况下,您不想拨打 strlen(s)
。通常,您应该使用 s.size()
,因为它渐近地更快。 strlen(s.c_str())
的需求如此之少,以至于冗长的细节微不足道。
This is actually a good thing. Most of the time, you don't want to call strlen(s)
. Usually, you should use s.size()
because it is asymptotically faster. The need for strlen(s.c_str())
is so rare, that the little bit of verbosity is insignificant.
强制使用 .c_str()
很好,因为它向程序读者显示它不是 std :: string
传递给函数/运算符,但为 char *
。通过隐式转换,不可能将一个与另一个区分开。
Forcing the use of .c_str()
is great because it shows the reader of the program that it is not a std::string
that is passed to the function / operator, but a char*
. With implicit conversion, it is not possible to distinguish one from the other.
这些问题并非无法克服。
Such problems are not insurmountable.
这篇关于为什么std :: string没有(显式)const char *类型转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!