目录
怎么判断调用了几次构造函数,拷贝构造函数,析构函数?.
定义两个全局变量m,n。每调用一次构造和拷贝构造都让m,n++,把m,n的值打印出来。
很明显,main函数没有调用A这个类的话m,n的值没有++。
用A对象类型创建一个变量aa1,此刻再打印出来m,n的值看:
m,n的值为1,说明调用了一次构造函数。
怎么看析构完还剩多少个:
每调用析构一次就m--,m还剩多少就是还有多少个没有被析构。
写一个拷贝构造函数,一个A对象类型的函数:
然后写一个函数调用:
我用linux下vim写一下
因为是c++,我用g++进行编译但是编译不了,然后我用YUM下载g++显示nothiing to do,说明已经下过g++了,那么肯定是g++需要更新的缘故:
使用这个命令更新gcc,++:
yum install update gcc+ gcc-c++
更新完成之后可以编译:
调用一次函数:
发现会调用一次拷贝构造:
这是因为调用函数就要传参,传参就要拷贝构造。
如果有这样的场景,没必要调用拷贝构造:
调用fun函数,函数再调用打印函数,打印函数只负责打印不用传参,不传参就没必要调用拷贝构造:
因此我们可以用引用传参:
这样就只会调用构造函数了:
#include<iostream>
using namespace std;
int n = 0;
int m = 0;
class A
{
public:
A()
{
n++;
m++;
}
A(const A& t)
{
n++;
m++;
}
~A()
{
m--;
}
};
A fun(A aa)
{
return aa;
}
int main()
{
A aa1;
A aa2;
cout<< n << " " << m << endl;
A();
cout << n << " " << m << endl;
fun(aa1);
cout << n << " " << m << endl;
return 0;
}
解析:
但是这样有个缺点,就是m,n的值容易被修改,有风险:
把m,n作为静态变量放在class A里面:
#include<iostream>
using namespace std;
class A
{
public:
A()
{
n++;
m++;
}
A(const A& t)
{
n++;
m++;
}
~A()
{
m--;
}
int Getm()
{
return m;
}
int print()
{
cout << m << endl;
return Getm();
}
private:
static int m, n;
};
int A::m = 0;
int A::n = 0;
A fun(A aa)
{
return aa;
}
int main()
{
A aa1;
A aa2;
aa1.print();
//cout << A::n << " " << A::m << endl;
//A();
//cout << aa1.m<< " " << aa1.n<< endl;
//fun(aa1);
//A* pst = nullptr;
//pst->m;
return 0;
}
这个时候m,n就不能被直接访问了,也就无法被修改:
只能在class A里面写函数:
class A:
{}
然后在类外调用函数来访问m,n:
如果把私有关了:那么下面这几种调用都可以
求1+2+3+...+n_牛客题霸_牛客网 (nowcoder.com)
这个题的意思就是:
思路:用静态变量的思路:
设一个静态变量i,让i每次+1,加n次
设一个静态变量ret,ret每次+i,加n次。
利用构造函数,用类对象类型创建一个大小为n的数组,就会调用n次构造函数,这样就形成了一个n循环次数,在构造函数里写循环语句:ret+i,i++;
最后再写一个函数,返回ret。
#include <linux/limits.h>
class sum{
public:
sum()
{
ret+=i;
i++;
}
static int print()
{
return ret;
}
private:
static int i;
static int ret;
};
int sum::i=1;
int sum::ret=0;
class Solution {
public:
int Sum_Solution(int n) {
sum a[n];
return sum::print();
}
};
画图解析:
内部类
所谓的内部类无非是在一个类里面包含一个类,那它与外部类有什么区别?
看下面代码,求sizeof(A)大小:
答案:
原因:内部类是独立的,它受类 域的限制,也就是说Class A和Class B是两个独立的类,下面这种情况才是sizeof(A)才是8:
写了内部类之后外部不能直接访问内部类:
需要先突破外层类才能访问内部类:
注意内部类可以直接访问外部类中的static成员,不需要外部类的对象/类名:
我们用同一道题来对比一下外部类和内部类:
求1+2+3+...+n_牛客题霸_牛客网 (nowcoder.com)
假设我们调用一次FUN函数就会调用一次拷贝构造,因为调用就要传参,传参就要拷贝构造:假设我们用Fun函数再调用一个打印函数:
print函数只用打印就可以了,所以我们无需传参,也就不需要再调用一次拷贝构造函数了,所以我们用引用:
为了防止被更改,我们给引用加一个const修饰一下:= 这是const对象不能修饰非const对象,这是权限的放大,所以我们给print函数也加个const缩小一下权限,这样Fun函数就可以修饰了:
Fun(A())是匿名对象,会调用构造函数,出了当前行就结束:
const引用会延长匿名对象的结束周期:
编译器的自动优化:
如图,调了三次函数,传了三次参,却只调了一次拷贝构造,这是编译器的优化:编译器认为频繁的调用拷贝构造太麻烦了:
例1:例2:例3:
内存管理
当我们不写析构函数的时候,下面程序中编号为1,2,3的三条语句的运行结果分别为:
class A
{
public:
A()
{
cout << "调用一次析构" << endl;
}
//~A()
//{
cout << "调用一次析构" << endl;
//
//}
private:
int _a;
};
int main()
{
A* p2 = new A[10];
free(p2); //1
//delete p2; //2
//delete[]p2; //3
return 0;
}
当我们写了析构函数后下面程序的运行结果分别为:
class A
{
public:
A()
{
cout << "调用一次析构" << endl;
}
~A()
{
cout << "调用一次析构" << endl;
}
private:
int _a;
};
int main()
{
A* p2 = new A[10];
free(p2); //1
//delete p2; //2
//delete[]p2; //3
return 0;
}
我们发现只有delete[ ]p2成功跑起来了,并且调用了十次析构。
解析:
当写了析构时:
为什么free(p2)和delete p2不行: