我有几个问题,我认为对于有C ++经验的人来说很容易回答,我会大胆提出TL的问题; DR
给出以下代码:
void stringTest(const std::string &s)
{
std::cout << s << std::endl;
}
int main()
{
stringTest("HelloWorld");
}
希望有人可以在我的思考过程中指出错误:
为什么在传递C样式字符串时,stringTest中的参数必须标记为const?是否存在使用其cstyle字符串构造函数的std :: string的隐式转换因此,“s”不再是对文字的引用(并且不需要是const)。
此外,cstyle字符串构造函数看起来是什么样的,编译器如何知道在看到时调用它:
stringTest("HelloWorld");
它是否只是将字符串文字识别为char *?
在研究复制构造函数时,我偶然发现了这些问题。我自己澄清的另一个快速问题......
在类似的情况下:
std::string s = "HelloWorld";
cstyle字符串构造函数是否用于实例化临时std :: string,然后使用字符串复制构造函数将临时字符串复制到“s”中?:
std::string(const std::string&);
答案 0 :(得分:2)
为什么在传递C-Style字符串时,stringTest中的参数必须标记为const?
只有在参数是引用时才需要,因为临时std::string
是从您传入的char const*
构建的,而非const
引用临时是非法的。
它是否只是将字符串文字识别为char *?
字符串文字是char const
数组,它会衰减到char const*
。由此,编译器推断它应该使用非explicit
构造函数std::string::string(char const *)
来构造临时。
cstyle构造函数是否用于实例化临时std :: string,然后使用字符串复制构造函数将临时字符串复制到“s”中?
比这复杂一点。是的,创建了一个临时的。但复制构造函数可能会被调用,也可能不会被调用;允许编译器跳过复制结构作为优化。但是仍然必须提供复制构造函数,因此以下内容将无法编译:
class String {
String(char const *) {}
private:
String(String const &);
};
int main()
{
String s = "";
}
此外,在C ++ 11中,将使用移动构造函数(如果提供);在这种情况下,不需要复制构造函数。
答案 1 :(得分:2)
为什么在传递C-Style字符串时,stringTest中的参数必须标记为const?
编辑: 临时工必须是不变的。见larsmans评论和回答,他是对的。
简单的理由:
void change(std::string& c) { c = "abc"; }
change("test"); // what should the code exactly do??
此外,cstyle字符串构造函数看起来是什么样的,编译器如何知道在看到它时调用它:
它为std::string
构造函数
string(char*)
在类似的情况下:
std::string s = "HelloWorld";
cstyle构造函数是否用于实例化临时std :: string,然后使用字符串复制构造函数将临时字符串复制到“s”中?: std :: string(const std :: string&amp;);
没有。在这个确切的情况下(TYPE variable = SOMETHING
),它与写TYPE variable(SOMETHING);
相同。因此,不使用复制。
答案 2 :(得分:2)
它是否只是将字符串文字识别为类似于 字符*?
原始问题的这一部分没有像我所希望的那样清楚地回答。尽管如此,我还是完全赞同(和投票通过)Yossarian对其余部分的回答。
基本上,当您在代码中看到字符串文字时,您需要了解编译器正在做什么。那个字符数组(就像任何c风格的字符串一样)实际上存储在一个完全不同的位置,而不是它所属的代码(取决于体系结构,数字文字可以存储在位置本身作为程序集的一部分/二进制指令)。这里的两个代码块“或多或少”等效(忽略缺少包含或名称空间声明):
int main(void)
{
cout << "Hello!" << endl;
return 0;
}
这更接近于“真正”发生的事情:
const char HELLO_STR[] = { 'H', 'e', 'l', 'l', 'o', '!', 0 };
int main(void)
{
cout << HELLO_STR << endl;
return 0;
}
请原谅我,如果我在数组init或其他方面犯了错误,但我认为这表达了我的意思,就是字符串文字“真正”存储的位置。它不是内联的,但对于定义它的程序的另一部分来说是一个不可见的常量。另外,一些(大多数?)编译器还将字符串文字“排列在一起”,这样如果你在50个地方使用相同的文字,它只存储其中一个,并且所有这些都引用回相同的常量,节省记忆。
所以请记住,无论何时使用字符串文字,你都会使用一个存在于“隐形”某处的const char [N],它被隐式转换为const char *。
答案 3 :(得分:0)
在此示例中,const string & s
需要从参数“HelloWorld”调用构造函数。使用的构造函数是类型转换构造。
string& s
不会这样做,因为s直接引用字符串对象。
类型转换由类似于
的内容定义 basic_string(const _CharT* __s);
使用typedef
typedef basic_string<char> string;
因此声明将评估为
basic_string(const char * __s)