c++ - 为什么显式定义拷贝构造函数后就无法通过编译了?
本文介绍了c++ - 为什么显式定义拷贝构造函数后就无法通过编译了?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
问 题
初学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
解决方案
因为C++规范允许编译器在这个时候优化掉不必要的拷贝构造。
GCC加上参数-fno-elide-constructors可以不优化。
虽然这个调用拷贝构造的过程是后来被优化掉了的。但是编译检查语法的时候仍然需要它存在的。而VC则是直接优化掉,根本不会调用拷贝构造函数。
优化了以后,Complex c3 = 3.14;这样的初始化表达式和Complex c3(3.14);是等价的了。
这篇关于c++ - 为什么显式定义拷贝构造函数后就无法通过编译了?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文