自定义string类里面拷贝构造函数代码:
string(const char* tmp) : str(new char[strlen(tmp) + 1])
{
std::cout << "call2" << std::endl;
strcpy(str, tmp);
}
string(string& tmp) : str(new char[strlen(tmp.str) + 1])
{
std::cout << "call3" << std::endl;
strcpy(str, tmp.str);
}
在main函数里面调用
string str = "hello";
报错提示:
error: invalid initialization of non-const reference of type 'string&' from an rvalue of type 'string'
note: initializing argument 1 of 'string::string(string&)'
string(string& tmp) : str(new char[strlen(tmp.str) + 1])
^
string str = "hello";
after user-defined conversion: string::string(const char*)
string(const char* tmp) : str(new char[strlen(tmp) + 1])
^
我在那个string(string& tmp)的参数前面加上一个const限定,就可以成功编译运行,请问这是为什么?
因为你这么定义的话,右值的
string
类型就无法成功匹配到构造函数了,const string&
能同时引用右值和左值,而string&
只能引用左值。还有像楼上说的,为了避免和
namespace
std
中的string
类型冲突,最好放到你自己的namespace
中或者改名。。你这里用混了吧,自定义的类叫string,标准的STL里的字符串也是string,冲突了,编译在匹配构造函数时,认为string& tmp 这个类型是匹配的STL里的string,而非你自定义的。
问题在这里
你把它换成
string str("hello");
应该就没有问题了。因为这里使用了
=
,所以这里没有匹配上一个合适的构造函数。string str = "hello";
可以看做是string str(string("hello"))
。string("hello")
可以正确的匹配上string(const char*)
这个构造函数,其返回一个临时的string对象,是一个右值。但是这个右值不知道如何转换为string&
或者const char*
类型去构造str
。报错
invalid initialization of non-const reference of type 'string&' from an rvalue of type 'string'
就是因为这个原因。然后再说这个
string str(string("hello"))
,千万不要以为这样会构造两次,其实是不会的。因为string("hello")
这里就已经把string
对象构造出来了,它就是str
,不会进行多次构造。这个问题的出现,看你用的是什么编译器。你用VS2013试试,就没有这样的问题了。