我想知道拥有和不拥有这样的 Actor 阵容的优缺点。在包括此处 Stack Overflow 在内的几个地方,我可以看到 const char*
cast 被认为是个坏主意,但我不确定为什么?
缺少 (const char*)
并强制始终使用 c_str()
转换会在编写通用例程和模板时产生一些问题。
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_str()
了。但是通过这种方式,模板函数不能同时用于 std::string
和 const char*
而不需要额外的努力。
作为一个问题,我可以看到一些运算符重载问题,但这些问题是可以解决的。
例如,正如 [eerorika] 指出的那样,通过允许隐式转换为指针,我们允许非自愿的字符串类参与 bool 表达式。但是我们可以通过删除 bool 运算符轻松解决这个问题。更进一步,可以强制转换运算符是显式的:
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;
}
最佳答案
I like to know pro's and con's for having and not-having such cast.
缺点:隐式转换的行为通常会让程序员感到惊讶。
例如,您希望从以下程序中得到什么?
std::string some_string = "";
if (some_string)
std::cout << "true";
else
std::cout << "false";
程序是否应该格式错误,因为 std::string
没有转换为 bool
?结果应该取决于字符串的内容吗?大多数程序员会有同样的期望吗?
对于当前的 std::string
,上面的格式是错误的,因为没有这样的转换。这很好。无论程序员期望什么,他们都会在尝试编译时发现自己的误解。
如果 std::string
有一个到指针的转换,那么也会有一个转换序列通过到指针的转换来 bool。上面的程序是良构的。无论字符串的内容如何,程序都会打印 true
,因为 c_str
永远不会为 null。如果程序员反而期望空字符串为假怎么办?如果他们从来没有打算采取任何一种行为,而是无意中使用了一个字符串怎么办?
下面的程序呢?
std::string some_string = "";
std::cout << some_string + 42;
您是否认为程序是病式的,因为字符串和 int
没有这样的运算符?
如果存在到 char*
的隐式转换,则上述代码将具有未定义的行为,因为它进行指针运算并访问其边界之外的字符串缓冲区。
// all below will not compile with strlen(s);
这其实是一件好事。大多数时候,您不想调用 strlen(s)
。通常,您应该使用 s.size()
,因为它渐近地更快。对 strlen(s.c_str())
的需求是如此罕见,以至于一点点冗长都是微不足道的。
强制使用 .c_str()
很棒,因为它向程序的读者表明传递给函数的不是 std::string
/运算符,而是一个 char*
。使用隐式转换,无法将两者区分开来。
... creates some problems when writing generic routines and templates.
这些问题并非无法克服。
关于c++ - 为什么 std::string 没有(明确的)const char* cast,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59076004/