代码:
#include <iostream> using namespace std; class Complex { public: Complex(double r, double i); Complex(Complex& c); Complex add(Complex c); void print(void); private: double real, image; }; Complex::Complex(double r, double i) :real(r), image(i) { cout << "调用两个参数的构造函数" << endl; } Complex::Complex(Complex& c) { real = c.real; image = c.image; cout << "调用拷贝构造函数" << endl; } void Complex::print(void) { cout << "(" << real << "," << image << ")" << endl; } Complex Complex::add(Complex c) { Complex y(real + c.real, image + c.image); return y; } void f(Complex n) { cout << "n="; n.print(); } void main(void) { Complex a(3.0, 4.0), b(5.6, 7.9); Complex c(a); cout << "a="; a.print(); cout << "c="; c.print(); f(b); c = a.add(b); c.print(); }
|
运行代码后显示:
调用两个参数的构造函数 调用两个参数的构造函数 调用拷贝构造函数 a=(3,4) c=(3,4) 调用拷贝构造函数 n=(5.6,7.9) 调用拷贝构造函数 调用两个参数的构造函数 (8.6,11.9)
|
分析程序的主要运行过程:
-
初始化对象 a: 使用Complex(double r, double i)
构造函数,传入3.0
和4.0
作为参数,初始化对象 a 的成员变量real
和image
。输出:
-
初始化对象 b: 使用Complex(double r, double i)
构造函数,传入5.6
和7.9
作为参数,初始化对象 b。输出:
-
初始化对象 c 通过拷贝构造函数: 使用拷贝构造函数Complex(Complex& c)
,以 a 作为参数,初始化 c,调用拷贝构造函数,使 c 的成员变量的值与 a 相同。输出:
-
打印对象 a 和 c 的值:调用print
方法输出 a 和 c 的值。输出:
-
调用函数f
:函数f
接受一个Complex
类型的参数。这里将对象 b 传递给函数f
。因为f
的参数是按值传递的,所以这里会调用Complex(Complex& c)
拷贝构造函数,创建 b 的一个副本 n ,然后在f
中打印 n 的值。输出:
-
使用add
方法:调用a.add(b)
,这里将对象 b 传递给函数add
。因为add
的参数是按值传递的,所以这里会调用Complex(Complex& c)
拷贝构造函数,输出:
在add
方法内部,创建了一个名为 y 的临时对象,用于存储相加后的结果。这一步调用了两个参数的构造函数Complex(double r, double i)
,输出:
-
将add
方法的返回值赋给对象 c
-
打印c的值。输出:
若将代码:
Complex Complex::add(Complex c)
|
改为:
Complex Complex::add(Complex & c);
|
即使用引用传递。
此时输出:
调用两个参数的构造函数 调用拷贝构造函数 a=(3,4) c=(3,4) 调用拷贝构造函数 n=(5.6,7.9) 调用两个参数的构造函数 (8.6,11.9)
|
可以看到通过引用传递可以避免创建参数的副本,不会触发Complex::Complex(Complex& c)
拷贝构造函数,可以提高程序的效率。
亦可使用operator+
来避免创建参数的副本。可将代码改为:
#include <iostream> using namespace std; class Complex { public: Complex(double r, double i); Complex(const Complex& c); Complex add(Complex &c); void print(void); Complex operator+(const Complex& c); private: double real, image; }; Complex::Complex(double r, double i) :real(r), image(i) { cout << "调用两个参数的构造函数" << endl; } Complex::Complex(const Complex& c) { real = c.real; image = c.image; cout << "调用拷贝构造函数" << endl; } void Complex::print(void) { cout << "(" << real << "," << image << ")" << endl; } Complex Complex::operator+(const Complex& c) { return Complex(real + c.real, image + c.image); } void f(Complex n) { cout << "n="; n.print(); }
int main() { Complex a(3.0, 4.0), b(5.6, 7.9); Complex c(a); cout << "a="; a.print(); cout << "c="; c.print(); f(b); c = a + b; c.print(); }
|
输出结果与上面相同。
此外,这里的c = a + b;
在c++11或优化的编译器中使用了移动赋值操作符operator=(Complex&&)
赋值给c
,但在老版本或者未优化的编译器中会调用拷贝赋值操作符,执行复制而占用空间。
要想实现日志效果,则可以在对象中添加operator=
拷贝赋值操作符:
Complex& operator=(const Complex& c) { real = c.real; image = c.image; cout << "调用拷贝赋值操作符" << endl; return *this; }
|
移动赋值操作符:
Complex& operator=(Complex&& c) noexcept { real = c.real; image = c.image; cout << "调用移动赋值操作符" << endl; return *this; }
|