我是否误解了此默认参数共享的范围

Have I misunderstood the scope of this default argument shared_ptr?

本文关键字:参数 共享 范围 默认 是否 误解      更新时间:2023-10-16

看一下:

#include <iostream>
#include <memory>
using Foo = int;
using FooPtr = std::shared_ptr<Foo>;
FooPtr makeFoo()
{
    FooPtr f{
        new Foo(),
        [](Foo* ptr) {
            delete ptr;
            std::cerr << "!n";
        }
    };
    return f;
}
void bar(FooPtr p = {})
{
    p = makeFoo();
}
int main()
{
    bar();
}
// Expected output: '!'
// Failure case: no output (deleter not invoked?)

我希望当bar()返回时,shared_ptr deleter会被调用,在我的64位CentOS 7系统中使用GCC 4.8.5,它可以。

但是,在我的32位CentOS 6系统上,使用GCC 4.8.2在DevToolset-2下(也是我的Raspberry Pi Toolchain下的i Think (,它没有。

查看代码,并在4.8中给定C 11的实验性质,这对我来说就像是编译器错误。但是我也可能会陷入某个地方的UB陷阱(或者只是误解了这些东西应该如何工作(。

谁有错?我应该如何修复它?


上工作
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/lto-wrapper
Target: x86_64-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu --enable-languages=c,c++,objc,obj-c++,java,fortran,ada,go,lto --enable-plugin --enable-initfini-array --disable-libgcj --with-isl=/builddir/build/BUILD/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/isl-install --with-cloog=/builddir/build/BUILD/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/cloog-install --enable-gnu-indirect-function --with-tune=generic --with-arch_32=x86-64 --build=x86_64-redhat-linux
Thread model: posix
gcc version 4.8.5 20150623 (Red Hat 4.8.5-16) (GCC)

失败

Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/opt/rh/devtoolset-2/root/usr/libexec/gcc/i686-redhat-linux/4.8.2/lto-wrapper
Target: i686-redhat-linux
Configured with: ../configure --prefix=/opt/rh/devtoolset-2/root/usr --mandir=/opt/rh/devtoolset-2/root/usr/share/man --infodir=/opt/rh/devtoolset-2/root/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --enable-languages=c,c++,fortran,lto --enable-plugin --with-linker-hash-style=gnu --enable-initfini-array --disable-libgcj --with-isl=/builddir/build/BUILD/gcc-4.8.2-20140120/obj-i686-redhat-linux/isl-install --with-cloog=/builddir/build/BUILD/gcc-4.8.2-20140120/obj-i686-redhat-linux/cloog-install --with-mpc=/builddir/build/BUILD/gcc-4.8.2-20140120/obj-i686-redhat-linux/mpc-install --with-tune=generic --with-arch=i686 --build=i686-redhat-linux
Thread model: posix
gcc version 4.8.2 20140120 (Red Hat 4.8.2-15) (GCC)

bar返回或称为bar的完整表达式的末端时,驱动器应调用。

如果我们查看[Expr.Call]/4(C 17草稿(,我们有

调用函数时,每个参数(11.3.5(的初始化(11.6,15.8,15.1(具有相应的参数。[...]当参数的寿命在定义返回或封闭全表达结束时的函数。[...]

因此,应在功能开始时将p初始化为null FooPtr,移动分配给MakeFoo的返回,然后在bar的末尾或main返回CC_11的CC_11末最终(又拨打Deleter(。<<<<<<<<<<<<

正如内森(Nathan(所表明的那样,我对指针寿命的假设是标准纠正的。

没有调用eLeter确实是GCC或libstdc 错误,鉴于链接的评论解决了它,可能是错误的60367,这些症状似乎相似,并且在GCC 4.8.5之前修复了。

。 。

= FooPtr{}替换= {}似乎是可行的解决方法。


请注意,在7.2中也有回归,一些较旧的" 8.0"躯干构建可能会在类似情况下引起不良行为(感谢Arne Vogel!(。