关于这段程序的几个疑问

来源:4-1 字符语法的常见陷阱上

lihsing

2022-12-09

老师,您好,我刚刚学完咱们这个课程的基础部分,我写了一个这样的小程序,
目的是为了对一个vector求均值时,避免重复计算,程序如下:

#include <vector>
#include <iostream>

class Q {
public:
    Q(): sum_(nullptr), mean_(nullptr) {}
	void Append(double &i) {
		data_.push_back(i);
	}
	double Sum() {
		if (sum_ == nullptr) {
            std::cout << "求和..." << std::endl;
			double temp = 0;
			for (auto it=data_.begin(); it!=data_.end(); it++) {
				temp += (*it);
			}
			sum_ = new double(temp);
		}
        return *sum_;
	}
    double Mean() {
        if (mean_ == nullptr) {
            std::cout << "求均值..." << std::endl;
            mean_ = new double(Sum() / data_.size());
        }
        return *mean_;
    }
	void Clean() {
		if (sum_ != nullptr) {
			delete sum_;
			sum_ = nullptr;
		}
        if (mean_ != nullptr) {
            delete mean_;
            mean_ = nullptr;
        }
	}
	~Q() {
		Clean();
	}
private:
    std::vector<double> data_;
    double *sum_;
    double *mean_;
};


int main() {
	Q q;
	double d1 = 1.0;
	double d2 = 2.0;
	double d3 = 3.0;
	double d4 = 4.0;
	q.Append(d1);
	q.Append(d2);
	q.Append(d3);
	q.Append(d4);
	std::cout << q.Mean() << std::endl;
	std::cout << q.Mean() << std::endl;
}

我有这样几个问题:

问题1

对于Sum方法Mean方法,由于方法内部计算出来的结果,需要在函数外部用到,是否必须使用new在堆区进行创建?

问题2

  1. 一个类的析构方法是否是为了删除该类在堆区产生的变量?
  2. 如果一个类没有在堆区创建变量,是否可以不写析构方法或者写一个空方法?

例如:

class A1 {
public:
    A1() {
        i = 1;
        j = 2;
    }
private:
    int i;
    int j;
}
class A2 {
public:
    A2() {
        i = new int(1);
        j = new int(2);
    }
    ~A2() {
        delete i;
        i = nullptr;
        delete j;
        j = nullptr;
    }
private:
    int *i;
    int *j;
}

A1因为没有堆区的变量,不写析构方法不会造成内存泄漏,而A2则必须写。

问题3

Append方法由于参数是一个引用,直接这样调用不行:

q.Append(5.0);

而必须这样:

double d5 = 5.0;
q.Append(d5);

有没有什么好方法能够避免临时变量d5?

写回答

1回答

quickzhao

2022-12-12

问题1: 这里没必要使用指针类型来定义sum和mean,这二者本身使用值类型就可以完成计算操作,这样不需要出现new;

问题2: 析构函数不仅仅是处理堆空间释放的问题,它可能包括系统中的文件句柄,数据库连接池等资源释放,所以一般来说析构函数是需要定义的;

问题3: 对于你这里的Append操作,它仅仅是添加一个double类型的值,其实不需要使用引用就可以;引用多数是在自定义的class对象中,用以节省空间而用。


0
2
quickzhao
回复
lihsing
是的,理论上来说没错。但是一般来说,C++在你不定义类的析构函数时会默认自动生成一个构造函数,但是如果有需要自己释放的资源则不要使用默认的析构函数,而且一般在继承体系中析构函数通常都定义成虚函数,因为每个类自己需要释放的资源并不一样。
2022-12-12
共2条回复

重学C++ ,重构你的C++知识体系

一部大片,一段历史,构建C++知识框架的同时重塑你的编程思维

3884 学习 · 1103 问题

查看课程