编译器对于C++构造函数的优化和C++17之后对构造函数的优化

近日结合李伟老师在C++构造函数课上讲的内容,跑了一些程序,发现了一些疑问。
程序如下

#include <iostream>
using namespace std;
class str
{
    public:
    str(int x):a(x)
    {
        cout<<"construct function"<<endl;
    }
    str(const str& str1):a(str1.a)
    {
        cout<<"copy construct function"<<endl;
    }
     str(str&& str1):a(move(str1.a))
     {
         cout<<"move construct function"<<endl;
     }
    str& operator =(const str& val)
    {
        a=val.a;
        cout<<"copy operator used"<<endl;
        return *this;
    }
    private:
        int a;
};
int main()
{
	str a{str(2)};
}

本来认为结果应该是先进行一次直接构造函数,在进行一次移动构造函数,但实际输出竟然是这样。
在这里插入图片描述
可以看出,结果显示只进行了一次直接构造,这与预想的结果不太相同。查阅了相关资料后发现,编译器对C++默认有一个优化。手册上的解释是这样的。

-fno-elide-constructors

The C++ standard allows an implementation to omit creating a temporary that is only used to initialize another object of the same type. Specifying this option disables that optimization, and forces G++ to call the copy constructor in all cases.
大意为:C++标准允许一种(编译器)实现省略创建一个只是为了初始化另一个同类型对象的临时对象。指定这个参数(-fno-elide-constructors)将关闭这种优化,强制G++在所有情况下调用拷贝构造函数。

编译时添加这个参数,运行结果如下
在这里插入图片描述
可以看出来结果符合我们的预期。
李伟老师在课程中提到最好不要对移动构造函数引入delete限定符,是因为C++17有一个优化,这句话听课的时候不太明白,先不加限定符在C++17下跑一下试试。
在这里插入图片描述
发现竟然又只输出了一条,但是我们明明加了-fno-elide-constructors,我认为老师所说的优化应该指的就是这个吧,不管加不加-fno-elide-constructors,编译器都会进行优化。

对这个程序移动构造函数添加了delete后,先在C++11标准下编译一下试试。
在这里插入图片描述
可以看出来,编译出现了错误,这就很迷了,之前明明分析的是编译器会默认对其构造函数引入优化,不应该没使用移动构造函数吗?
再在C++17下跑一下。
在这里插入图片描述
编译并没有出错。
于是我认为,整个的过程应该是,编译器默认会对构造函数引入优化,但C++11标准下这个优化并不彻底,不能对移动构造函数加delete(虽然没有用到移动构造函数),且这个优化可以通过添加-fno-elide-constructors来关闭。而C++17后这个优化就很彻底,构造函数加不加delete已经无所谓了(反正也没用到),且无法通过加-fno-elide-constructors来关闭。而之所以不建议对移动构造函数加delete的原因之一可能就是怕这个不彻底的优化被发现吧?(个人猜测)

只是个人理解,如有问题请指出!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值