初学C++,遇到了这样一个问题,代码如下:
#include <iostream>
using namespace std;
class Complex {
float real, imag;
public:
Complex(float r = 0.0, float i = 0.0):real(r), imag(i) {
cout << "Complex constructor called" << endl;
}
Complex (Complex& complex):real(complex.real), imag(complex.imag) {
cout << "Complex copy constructor called" << endl;
}
int main() {
Complex c3 = 3.14;
}
运行的时候会有编译错误,如下:
foobar.cpp:42:13: error: no viable constructor copying variable of
type 'Complex'
Complex c3 = 3.14;
^ ~~~~
foobar.cpp:10:5: note: candidate constructor not viable: expects an
l-value for 1st argument
Complex (Complex& complex):real(complex.real), imag(comp...
^
然而,当我删掉我显式定义的拷贝构造函数后,就可以正常编译了,即:
#include <iostream>
using namespace std;
class Complex {
float real, imag;
public:
Complex(float r = 0.0, float i = 0.0):real(r), imag(i) {
cout << "Complex constructor called" << endl;
}
int main() {
Complex c3 = 3.14;
}
这样就可以正常编译,请问这是为什么呢?
我用的是 g++ 4.2.1
目前我知道的是:当执行"Complex c3 = 3.14"时发生这些:先调用我显式定义的默认构造函数"Complex(float r = 3.14, float i = 0.0)"创建了一个临时对象,然后利用拷贝构造函数(如果有合法的)去创建c3,然后讲临时对象析构。
其实我的问题有两个:
1)为什么默认的拷贝构函数造能通过编译
2)为什么我定义的拷贝构函数造不能通过编译
补充:之前的问题已解决,但是现在遇到了新的问题
代码如下:
#include <iostream>
using namespace std;
class Complex {
float real, imag;
public:
Complex(float r = 0.0, float i = 0.0):real(r), imag(i) {
cout << "Complex constructor called" << endl;
}
Complex(const Complex& complex):real(complex.real), imag(complex.imag) {
cout << "Complex copy constructor called" << endl;
}
};
int main() {
Complex c = 3.22;
}
可以通过编译,但是输出结果为:
Complex constructor called
并没有调用拷贝构造函数啊,为什么呢?是被编译器优化了吗?
如果不需要调用拷贝构造函数,那为什么之前不加const限定的拷贝构造函数不能通过编译呢?
我用的编译器是 g++ 4.2.1
Because the C++ specification allows the compiler to optimize out unnecessary copy construction at this time.
GCC plus parameter -fno-elide-constructors does not need to be optimized.
Although the process of calling copy construction was later optimized. But it still needs to exist when compiling and checking the syntax. VC is directly optimized and does not call the copy constructor at all.
After optimization, the initialization expression Complex c3 = 3.14; is equivalent to Complex c3(3.14);.
Complex c3=3.14;
This copy constructor is a constant, so you should change the definition to
Complex (const Complex& complex);
After adding the const keyword, non-const variables can also be copy-constructed, so the general copy constructor All add const.
Hope this helps!
Sorry! My previous answer was wrong
for
Complex c3=3.14;
because this 3.14 is not a complex object, the system should treat it as a float type object, so its call will be equivalent to:Complex c3(3.14);
The constructor you defined is called, and this process is initialization, and the default copy constructor is not called.
The copy constructor is called when an object of the same class is copied, that is, it is called when the Complex object is copied.
For example:
Complex c4=c3;
Only then will call the copy constructor .I found no compilation errors when I ran your previous code on my computer, so I guess it’s the compiler. I’m not familiar with this aspect so I can’t answer it for you.
I hope my answer will be helpful to you!
If the copy constructor is provided in the class, the default parameterless and parameterized constructors will no longer be provided, so deleting the copy constructor will allow normal compilation
If you forget the curly braces and semicolons when posting the code, this is a clang bug...
It can be compiled with Visual C++ 14.0 (VS2015).
Run result:
Then for the question you added:
What it does is indeed initialization, not assignment. Explained in A Tour of C++ by Bjarne Stroustrup, the father of C++: