强制省略副本?gcc 5.4.1
Mandatory copy elision? gcc 5.4.1
我目前正在努力实现c++和复制省略,特别是"命名返回值优化"(NRVO),以便能够实现工厂函数模式。我无法在不同的编译器之间获得一致的行为。我的mwe:
#include <iostream>
struct base {
virtual ~base() { std::cout << "dtor basen"; }
};
struct derived : public base {
~derived() { std::cout << "dtor derivedn"; }
};
derived f() { return derived(); }
int main(int argc, char *argv[]) {
std::cout << "startn";
new derived(f());
std::cout << "done. should have leaked!n";
}
注意:删除虚拟基本dtor可以解决这个问题,但我需要它来进行实际实现。
在gcc 5.4.0的情况下,调用dtor,不执行复制省略:
$ g++ test2.cpp && ./a.out
start
dtor derived
dtor base
done. should have leaked!
当使用gcc 5.4.1(Ubuntu称之为5.4.1,我认为这是svn-head)时,我能拿到的所有clangs以及其他各种gcc都会执行省略并成功泄漏内存:
$ g++ test2.cpp && ./a.out
start
done. should have leaked!
当我在互联网上阅读不同的地方时,编译器被允许进行复制省略,但不是必需的。只有c++17引入了有保证的拷贝省略。那么,这是gcc 5.4.0中的一个错误,还是只是以不同的方式实现了标准?
复制省略在C++17之前是一个可选的优化,即使在C++17中,它也只是在某些情况下是强制性的。据我所知,即使在C++17中,(N)RVO副本省略也不是强制性的——唯一强制性的副本省略情况是使用临时初始化。
(N) RVO不应改变程序的行为,也不应要求程序正常运行。您应该以这样一种方式编写代码,即无论(N)RVO如何,它都能正常工作,并且在(N)RV启动时工作得更快。
在gcc 5.4.0的情况下,调用dtor,不执行复制省略:
start dtor derived dtor base done. should have leaked!
实际上,执行了复制省略。否则你会看到
start
dtor derived
dtor base
dtor derived
dtor base
done. should have leaked!
这里有两个复制省略的机会。一个是f
中的RVO(注意它不是NRVO,只是常规的未命名RVO),另一个是从临时复制*derived
的构造。GCC 5.4.0执行了一个可能的副本省略。
所有。。。执行省略并成功泄漏内存
GCC 5.4.0也成功地泄露了derived
所指向的内存。其他编译器从未创建过5.4.0所做的临时文件,后来又将其销毁。
当我在互联网上阅读不同的地方时,编译器可以执行复制省略,但不是必需的。
正确。
那么这是gcc 5.4.0 中的一个错误吗
否。不总是实现复制省略的编译器是符合标准的。请参阅我之前引用的问题中突出显示的部分。
- 如何在openssl-ecc中获取十六进制格式的私钥
- CMake项目Boost库错误:Boost/config/compiler/gcc.hpp:165:10:致命错误:cs
- 奇怪的结构&GCC&clang(void*返回类型)
- GCC本机矩阵运算库
- PowerPC ppc64le上的Gcc Woverloaded虚拟错误
- gcc和c++17的过载解析失败
- 如何将包含epoch时间的十六进制字符串转换为time_t
- 数据成员SFINAE的C++17测试:gcc vs clang
- 将字符指针十六进制转换为字符串并保存在文本文件C++中
- GCC对可能有效的代码抛出init list生存期警告
- 如何解决gcc编译器优化导致的centos双编译器设置中的分段错误
- 使用 GCC 卸载的 OpenMP 卸载失败,并出现"Ptx assembly aborted due to errors"
- 如何将一个ostringstream十六进制字符串字符对转换为单个unit8t等价的二进制值
- 为什么与常规GCC不同,即使有"学究性错误",MinGW-GCC也能容忍丢失的返回类型
- 使用gcc从静态链接的文件中查找可选符号
- 普通环路未使用gcc 4.8.5自动矢量化
- 如何在C++中用std::cout正确显示带十六进制的字符串文本
- 有了gcc,是否可以链接库,但前提是它存在
- 在clang++预处理器中确定gcc工具链版本
- 为什么 gcc 编译这个而 msvc 没有