我正在尝试自学C ++,我正在进行有关构造函数的基本练习。我有一个程序出乎意料地表现出来:
Fraction.h:
#include <iostream>
#ifndef FRACTION_H
#define FRACTION_H
using namespace std;
class Fraction
{
private:
int num;
int denom;
static int gcd(int a, int b);
void reduce();
public:
Fraction(int n=0, int d=1);
Fraction(Fraction& f);
~Fraction();
Fraction& operator=(const Fraction& f);
friend Fraction operator+(const Fraction& f1, const Fraction& f2);
friend ostream& operator<<(ostream& out, const Fraction& f);
};
#endif // FRACTION_H
Fraction.cpp(省略了一些实现):
#include "../include/Fraction.h"
#include <cassert>
#include <iostream>
using namespace std;
int Fraction::gcd(int a, int b) {
// implementation omitted
}
void Fraction::reduce() {
// implementation omitted
// this just reduces fractions to lowest terms, like 3/6 to 1/2
}
Fraction::Fraction(int n, int d) {
cout << "new fraction, n=" << n << ", d=" << d << endl;
assert(d != 0);
if (d < 0) {
num = -n;
denom = -d;
} else {
num = n;
denom = d;
}
reduce();
}
Fraction::Fraction(Fraction& f) {
cout << "copy fraction " << f << " at " << &f << endl;
num = f.num;
denom = f.denom;
}
Fraction::~Fraction() {
}
Fraction& Fraction::operator=(const Fraction& f) {
cout << "assign fraction to " << f << " at " << &f << endl;
if (this == &f)
return *this;
num = f.num;
denom = f.denom;
return *this;
}
Fraction operator+(const Fraction& f1, const Fraction& f2) {
cout << "adding " << f1 << " and " << f2 << endl;
return Fraction(f1.num * f2.denom + f2.num * f1.denom,
f1.denom * f2.denom);
}
ostream& operator<<(ostream& out, const Fraction& f) {
out << f.num << "/" << f.denom;
return out;
}
main.cpp中:
#include "include/Fraction.h"
#include <iostream>
using namespace std;
int main()
{
Fraction f1(1, 3);
Fraction f2(1, 2);
cout << f1 << endl;
cout << f2 << endl;
cout << (f1 + f2) << endl;
return 0;
}
当我运行它时,前两个打印语句按预期输出1/3
和1/2
,但第三个打印语句打印0/1
而不是5/6
。从我的调试语句中,我通过Fraction(int, int)
构造函数创建了5/6,但由于某种原因,它随后被调用0/1。当我删除复制构造函数时,代码打印出5/6
。这里发生了什么,如何在不删除复制构造函数的情况下修复它?
答案 0 :(得分:7)
复制构造函数的签名应为
Fraction(const Fraction&);
不的
Fraction(Fraction&);
当你执行return Fraction(...);
时,编译器必须调用Fraction(const Fraction&)
,因为返回的分数是临时的,但由于你没有定义它,你的编译器会发生奇怪的事情。您的编译器表现得非常奇怪,并允许您以某种方式使用默认构造函数,何时应该发出错误。在gcc上按原样编译代码不起作用,你必须进行我提到的修改,并且应该修复它。
此外,您的编译器未在该函数上使用RVO这一事实暗示您使用的是非常旧的和/或糟糕的编译器。