编译器的优化问题(构造、拷贝)、linux如何取消优化。

 编译器优化问题:

不同编译器优化是不一样的,下面代码我都用的vs2019,并且在Debud模式下。(Release也会进行优化)

下面测试的时候我先采用Debug模式测试。

先写一个简单的类,进行打印测试:

class A
{

public:
	A()
	{
		cout << "A()" << endl;
	}

	A(const A& a)
	{
		cout << "A(const A& a)" << endl;
	}

	A& operator=(const A& a)
	{
		cout << "A& operator=(const A& a)" << endl;
        
        return *this;
	}


	~A()
	{
		cout << "~A()" << endl;
	}
};

下面代码运行的话,会打印几次构造?几次拷贝?

void f1(A a)
{

}

int main()
{
	A a1;
    f1(a1);

	return 0;
}

首先 a1 肯定构造这是一次构造没问题,那么 a1 传给 f1() 是什么呢?

 这里 a1 传给 f1 的时候发生了拷贝,不是 a1 直接给 a,而是中间产生了一个临时变量 a1 先拷贝给临时变量,然后临时变量再传给了 a,下面画图解释:

所以打印出来是 1次构造+1次拷贝。 

那么下面这个代码呢?几次构造,几次拷贝?

void f2(A& a)
{

}

int main()
{
	A a1;
	f2(a1);

	return 0;
}

注意看这里的 f2() 函数里面的形参我加了引用!再结合前面我发的引用结合一下,所以这里应该是几次构造?几次拷贝?

答案:1次构造+0次拷贝,打印看一下:

那么为什么呢?结合前面写的关于引用的文章,引用做参数可以减少拷贝,提高效率。

增加难度,下面结合匿名对象来看编译器是如何优化的。

下面代码运行之后几次构造,几次拷贝构造?

void f1(A a)
{

}

int main()
{

	f1(A());

	return 0;
}

这里运行之后是 1次构造+0次拷贝构造,运行结果如下:

 

但是,那么不优化是什么呢?

不优化的话是 1次构造+1次拷贝。优化因为构造好了之后,再传给 f1 的时候,发生了优化,编译器直接合二为一,优化掉了拷贝。

结论:连续一个表达式步骤中,连续构造一般都会优化,合二为一。(这里还牵扯栈帧方面的知识)

那么再继续,下面代码几次构造,几次拷贝?

A f3()
{
	A ret;
	return ret;
}

int main()
{

	f3();

	return 0;
}

答案:1次构造+1次拷贝。

首先 f3 函数内部 A 先构造了一个 ret 对象没问题吧,那么拷贝哪里来的?还是一样结合前面的,这里返回是传值返回,返回的时候先拷贝给临时对象,然后这个临时对象在返回给调用 f3 的地方,所以发生了拷贝。

那么为什么不用引用返回减少拷贝?

这里的 ret 是局部对象,出了 f3 的域就销毁了,你再想通过引用去找那么访问的就是随机值。

那么继续,下面代码几次构造,几次拷贝?

A f3()
{
	A ret;
	return ret;
}

int main()
{

	A a = f3();


	return 0;
}

答案:优化之后: 1次构造+1次拷贝,那么不优化呢?
不优化是1次构造+2次拷贝,为什么呢?

结合上面的例子,这里两次拷贝应该不难,优化之后,编译器就好比直接通过拷贝一次临时对象传给了a(这里牵扯栈帧的知识)

下面难道再提升,下面代码几次构造,几次拷贝?

A f4(A a)
{
	A a1(a);
	A a2(a1);

	return a2;
}

int main()
{
	A aa;

	A aa1 = f4(aa);

	return 0;
}

 答案:优化之后,1次构造+4次拷贝;不优化是1次构造+5次拷贝,原因如下:

 绿色的线是优化之后的,蓝色是没优化的时候,这里编译器优化处理了,通过一次临时对象拷贝给了 aa1。

那么继续,下面代码几次构造,几次拷贝?

A f4(A a)
{
	A a1(a);
	A a2(a1);

	return a2;
}

int main()
{
	A aa;

	A aa1 = f4(f4(aa));

	return 0;
}

答案:优化之后是1次构造+7次拷贝;不优化是1次构造+9次拷贝。原因如下:

优化之后的:

 

 不优化之后的:

 这个就是编译器优化之后和优化之前的对比,编译器优化依不同编译器不同不一样,linux环境下也是不一样,linux可以加参数取消优化,加的参数是 -fno-elide-constructors 这个参数加一下可以运行看一下结果,我就举最后一个例子试一下,如下:

运行结果如下:1次构造+9次拷贝 

 以上就是编译器优化的例子,根据不同场景不同编译器优化也是不一样的。

阅读终点,创作起航,您可以撰写心得或摘录文章要点写篇博文。去创作
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wihkum

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值