初学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);과 동일합니다.
Complex c3=3.14;
이 복사 생성자는 상수이므로 정의를
Complex (const Complex& complex);
으로 변경해야 합니다.const 키워드를 추가한 후 const가 아닌 변수도 복사 생성할 수 있으므로 일반 복사는 생성자 모두 const를 추가합니다.
도움이 되었기를 바랍니다!
죄송해요!
복사 생성자는 동일한 클래스의 객체가 복사될 때, 즉 Complex 객체가 복사될 때 호출됩니다.에 대한 내 이전 대답은 틀렸습니다.
Complex c3=3.14;
이 3.14는 복잡한 객체가 아니기 때문에 시스템은 이를 부동 소수점 유형 객체로 처리해야 하므로 해당 호출은Complex c3(3.14);
정의한 생성자 가 호출되는데, 이 과정이 초기화이고, 기본 복사 생성자는 호출되지 않습니다.
예:
이전 코드를 내 컴퓨터에서 실행했을 때 컴파일 오류를 발견하지 못했기 때문에 컴파일러 때문인 것 같습니다. 이 부분에 대해 잘 알지 못해서 답변해 드릴 수 없습니다.그때에만
Complex c4=c3;
복사 생성자 를 호출합니다.클래스에 복사 생성자가 제공되면 기본 매개변수 없는 생성자와 매개변수화된 기본 생성자는 더 이상 제공되지 않으므로 복사 생성자를 삭제하면 정상적인 컴파일이 가능합니다
코드를 게시할 때 중괄호와 세미콜론을 잊어버리면 클랭 버그입니다...
Visual C 14.0(VS2015)으로 컴파일 가능합니다.
으아악실행 결과:
으아악그리고 추가하신 질문에 대해:
으아악이것이 하는 일은 실제로 할당이 아니라 초기화입니다. C 의 아버지인 Bjarne Stroustrup이 A Tour of C 에서 설명했습니다.
으아악 으아악