最近开始学习c++, 自己写了点小代码, 碰到一个问题现在还解决不了.
Test.h
#ifndef GEEK_TEST_H
#define GEEK_TEST_H
#include <cstring>
class Test{
public:
Test(char* ptr){
printf("aaaa");
if(ptr){
this->ptr = new char[strlen(ptr) + 1];
strcpy(this->ptr, ptr);
} else{
this->ptr = new char[1];
ptr[0] = '\0';
}
}
Test(const Test& test){
printf("bbb");
this->ptr = test.ptr;
}
char* ptr;
};
#endif //GEEK_TEST_H
main.cpp
#include <iostream>
#include "Test.h"
using namespace std;
int main() {
Test y = "haha";
return 0;
}
这样编译运行是正常的, 但是当我去掉Test.h中第二个构造函数参数列表中的const
之后, 就报错了... 也就是把第二个构造函数改成这样 :
Test(Test& test){
printf("bbb");
this->ptr = test.ptr;
}
报错也奇怪 :
/Applications/CLion.app/Contents/bin/cmake/bin/cmake --build /Users/zhangzhimin/Library/Caches/CLion2016.1/cmake/generated/geek-ef0ba4bc/ef0ba4bc/Debug --target geek -- -j 8
Scanning dependencies of target geek
[ 50%] Building CXX object CMakeFiles/geek.dir/main.cpp.o
/Users/zhangzhimin/ClionProjects/geek/main.cpp:7:14: warning: ISO C++11 does not allow conversion from string literal to 'char *' [-Wwritable-strings]
Test y = "haha";
^
/Users/zhangzhimin/ClionProjects/geek/main.cpp:7:10: error: no viable constructor copying variable of type 'Test'
Test y = "haha";
^ ~~~~~~
/Users/zhangzhimin/ClionProjects/geek/Test.h:20:5: note: candidate constructor not viable: expects an l-value for 1st argument
Test( Test& test){
^
1 warning and 1 error generated.
make[3]: *** [CMakeFiles/geek.dir/main.cpp.o] Error 1
make[2]: *** [CMakeFiles/geek.dir/all] Error 2
make[1]: *** [CMakeFiles/geek.dir/rule] Error 2
make: *** [geek] Error 2
希望有大神帮忙解决...
Test y = "haha";
In this statement, the compiler first uses Test(char ptr) to implicitly convert the string into the Test temporary object. The object of this temporary conversion is an rvalue and cannot be potentially modified. Passing a const char type to char* generated the first warning.
2. Then try to find a copy constructor and assign this temporary object object to y. The compiler only found Test(Test& test). There is no const modification here. The compiler refused to pass it and reported the second error. The third tip adds that the chosen copy constructor is Test(Test& test).
The most troublesome thing about C++ is the complexity. Each compiler has inconsistent interpretation or leniency of the specifications. Therefore, when using C++, you must not only ensure that there are no errors, but also preferably eliminate all warnings.
Using a const char* to initialize char* is not recommended in C++11 and later, and the compiler will report a warning. Just put the first constructor + const
The key is the line of code Test y = “haha”
A friend reminded me that it might be the compiler. I tried it with vs2015, and it instantly exploded and passed directly (I used the mac terminal before)... What do friends think? I just read the c++ documentation, which is When it comes to copy constructors, they can be const or not.