问题描述
最近开始学习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 8Scanning 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 1make[2]: *** [CMakeFiles/geek.dir/all] Error 2make[1]: *** [CMakeFiles/geek.dir/rule] Error 2make: *** [geek] Error 2
希望有大神帮忙解决...
问题解答
回答1:Test y = 'haha';
这条语句,编译器首先用 Test(char ptr) 隐式的 字符串转换为 Test 临时对象。这个临时转换的对象是一个右值,不能有潜在的修改。 把一个const char 型 传给 char* ,产生了第一个告警。2.接着尝式找一个 拷贝构造函数 将这个临时对象对象赋给 y, 编译器只找到了 Test(Test& test), 这里没有 const 修饰, 编译器拒绝传递,报了第二个错误。第三个提示补充说明 选取的 拷贝构造函数 是 Test(Test& test)。
C++ 最头痛的就是复杂性,各编译器对规范的解释或宽严不一致,因些使用C++不仅要保证没有错误,最好还要消除所有的告警。
回答2:拿一个const char* 来初始化 char* 在C++11及以后也是不推荐的,编译器会报warning。你把第一个构造函数+const就好了
回答3:关键是 Test y = “haha” 这行代码
回答4:朋友提醒我可能是编译器的原因, 用vs2015试了下, 瞬间爆炸直接通过(之前用的是mac的终端)... 朋友们怎么看, 同时刚看了下c++的文档, 里面说拷贝构造函数, 可以是const的, 也可以不是.
ISO C++03:12.82 A non-template constructor for class X is a copy constructor if its first parameter is of type X&, const X&,volatile X& or const volatile X&, and either there are no other parameters or else all otherparameters have default arguments (8.3.6).106) [Example: X::X(const X&) and X::X(X&, int=1)are copy constructors.