Phi*_*ler 16 c++ abi language-lawyer copy-elision c++17
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0135r0.html
上述"保证副本Elision"提案在2016年6月在芬兰奥卢举行的会议上被投票选入C++工作文件,然后被投票作为委员会草案出版.希望明年能够成为C++ 17标准的出版物.
该提案阐明了涉及临时对象的各种值类别,以在某些用例中强制执行复制构造函数调用.
我的问题是"这些新要求可能会破坏编译器的ABI兼容性,这些编译器可能以前没有在这些情况下完成复制,或者是以不符合新要求的方式实现的吗?"
我正在考虑初始化之类的东西,当创建对象时可以内联,而不是在跨越编译单元边界时.
Nic*_*las 12
调用函数时,函数必须返回一个值.该值需要内存才能存在,但返回值需要超出函数本身.ABI定义了这一切是如何工作的.一般来说,这是由调用者提供一块大小/对齐的内存来为函数返回值.
因此,如果函数计算一个值并返回它,它必须(理论上)将该计算值复制到返回值存储器中.当调用者检索它时,它必须(理论上)将该返回值内存复制到其他堆栈对象中以供以后使用.
非保证副本省略表示这些副本都不是必需的.在返回函数方面,允许编译器在生成该值时在内部简单地使用返回值内存,因此return语句不必复制任何内容.在接收端,如果将使用内存来初始化堆栈对象,则不必将其复制到该内存中.
保证副本省略说如果接收方正在初始化相同类型的对象,则接收方将不会考虑该对象是否具有复制/移动构造函数.因此,调用函数的代码auto t = Func();不会将其视为潜在的复制操作t.编译器处理该代码将Func使用堆栈空间中的返回值内存进行调用t.
在被调用者方面,如果直接返回prvalue,则不需要存在复制/移动构造函数.被调用者将直接在返回值存储器中构造prvalue.
事情就是这样:ABI并不关心这些.所有ABI关心的都是低级记忆.也就是说,只要调用者传递适当大小和对齐的返回值内存,并且被调用者正在使用适当类型的对象初始化该内存...... ABI 并不关心.
如果调用者想要将该返回值存储器用于以后的操作,那对ABI来说没问题.如果被调用者想要将数据直接初始化到返回值存储器而不是复制它,则ABI将不会注意到.
ABI定义了接口; 你使用该界面做什么取决于你.
例如,考虑返回值的Itanium ABI.它允许类类型存储在寄存器中,但前提是它们具有普通的复制/移动构造函数.否则,无论其内容如何,它们都必须在调用函数提供的内存中构造.如果这个类很容易复制,那么你就无法区分elision和non-elision.
ABI可能对此功能造成问题的唯一方法是ABI是否任意决定相对于彼此存储返回值(可能是参数)的位置.也就是说,ABI强制调用者将对象放置在相对于参数的特定位置的堆栈上.
这样的ABI能存在吗?我没有特别的知识可以说它不能.可以?我很怀疑它,因为这样一个ABI会使elision一般很难.