#include
#include
using namespace std;
struct A
{
int a[10000];
};
void TestFunc1(A* a)
{
}
void TestFunc2(A& a)
{
}
void TestRefAndValue()
{
A a;
// 以值作为函数参数
size_t begin1 = clock();
for (size_t i = 0; i < 100000; ++i)
TestFunc1(&a);
size_t end1 = clock();
// 以引用作为函数参数
size_t begin2 = clock();
for (size_t i = 0; i < 100000; ++i)
TestFunc2(a);
size_t end2 = clock();
// 分别计算两个函数运行结束后的时间
cout << "TestFunc1(A*)-time:" << end1 - begin1 << endl;
cout << "TestFunc2(A&)-time:" << end2 - begin2 << endl;
}
int main()
{
TestRefAndValue();
return 0;
}
void Swap(int& x, int& y)
{
int tmp = x;
x = y;
y = tmp;
}
#include
#include
using namespace std;
struct A
{
int a[10000];
};
A a;
// 值返回
A TestFunc1()
{
return a;
}
// 引用返回
A& TestFunc2()
{
return a;
}
void TestReturnByRefOrValue()
{
// 以值作为函数的返回值类型
size_t begin1 = clock();
for (size_t i = 0; i < 100000; ++i)
TestFunc1();
size_t end1 = clock();
// 以引用作为函数的返回值类型
size_t begin2 = clock();
for (size_t i = 0; i < 100000; ++i)
TestFunc2();
size_t end2 = clock();
// 计算两个函数运算完成之后的时间
cout << "TestFunc1 time:" << end1 - begin1 << endl;
cout << "TestFunc2 time:" << end2 - begin2 << endl;
}
int main()
{
TestReturnByRefOrValue();
return 0;
}
#include
using namespace std;
int& Count()
{
static int n = 0;
n++;
// ...
return n;
}
int main()
{
int ret = Count();
cout << ret << endl;
return 0;
}
#include
using namespace std;
int& Count(int x)
{
int n = x;
n++;
return n;
}
int main()
{
int& ret = Count(10);
cout << ret << endl;
return 0;
}
因为此时其实你画张图就很容易明白,此时此刻这个ret就是n的引用,但是变量n所在的内存空间早在函数退出的时候就已经还给操作系统了,这时候就需要去看这个函数栈帧销毁之后到底有没有被清理掉,如果没有清理栈帧,那么ret结果侥幸是正确为11。如果说清理了栈帧,那么ret的结果就是随机值,事实上这时候已经构成了非法访问
9. 问答3:ret分别多少? 侥幸11,21
#include
using namespace std;
int& Count(int x)
{
int n = x;
n++;
return n;
}
int main()
{
int& ret = Count(10);
cout << ret << endl;
Count(20);
cout << ret << endl;
return 0;
}
这个还是关于函数栈帧的问题,这边可以发现就是当你这个函数栈帧销毁的时候,但此时此刻原先这个函数栈帧还没有被清理掉,所以此时此刻你去访问ret(n的引用)还是能够访问的到值,一开始是11。然后后面又去调用了count函数,相当于在原先刚刚被摧毁掉的函数栈帧那块空间上又开辟了一个函数栈帧(这两个函数是一模一样的,所以说原先n的那块空间,现在又给到了数字20,然后加一变成了21),但当这个函数的函数栈帧也被销毁之后,它还是没有被清理掉,因此访问的话ret就为21。但实际上两次访问都是构成了非法访问,因为ret此刻所存在的内存空间已经是属于操作系统了,但只需稍微改动,便能破坏原先侥幸尚存的未被处理的内存里面的分步状况
10. 具体例子:比方说现在用一个函数就可以实现对顺序表的指定位置的访问与修改
因为我这个函数返回的是整个顺序表当中第pos个元素的引用,属于是引用返回,返回一方面他确实可以提高效率,减少拷贝,引用的第二个功能就是说可以去修改它的返回值,读写返回值,非常强大
他这个权限主要针对的就是对于一个常量还是变量的可读可写的问题,但是各个外号与变量名之间的权限互不干涉与交叉。虽然他们指向的都是同一内存空间。
#include
#include
using namespace std;
int main()
{
const int a = 10;
int& b = a;
return 0;
}
#include
#include
using namespace std;
int main()
{
const int a = 10;
const int& b = a;
return 0;
}
#include
#include
using namespace std;
int main()
{
const int a = 10;
int c = a;
double n = a;
return 0;
}
#include
#include
using namespace std;
int main()
{
int a = 10;
const int& b = a;
int& c = a;
return 0;
}
#include
#include
using namespace std;
int main()
{
double a = 1.1;
double& b = a;
return 0;
}
#include
#include
using namespace std;
int main()
{
double a = 1.1;
int& b = a;
float& c = a;
return 0;
}
#include
#include
using namespace std;
int main()
{
double a = 1.1;
const int& b = a;
const float& c = a;
return 0;
}
int func1()
{
static int x = 0;
return x;
}
int& func2()
{
static int x = 0;
return x;
}
int main()
{
int& ret1 = func1(); // 权限放大
const int& ret1 = func1(); // 权限平移
int ret1 = func1(); // 拷贝
int& ret2 = func2(); // 权限平移
const int& rret2 = func2(); // 权限缩小
return 0;
}