首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >我是否误解了这个默认参数shared_ptr的范围?

我是否误解了这个默认参数shared_ptr的范围?
EN

Stack Overflow用户
提问于 2018-03-26 18:17:35
回答 2查看 390关注 0票数 7

看一看这个:

代码语言:javascript
复制
#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?)

我期望shared_ptr删除器在bar()返回时被调用,在使用GCC 4.8.5的64位CentOS 7系统上,它会调用。

然而,在我的32位CentOS 6系统上使用GCC 4.8.2下的devtoolset-2 (我也认为在gcc-linaro-arm-linux-gnueabihf-4.8-2013.10_linux下,我的覆盆子Pi工具链),它没有。

看看代码,并考虑到C++11在4.8中的实验特性,我觉得这闻起来像是一个编译器bug。但我也可能在某个地方掉进了UB陷阱(或者只是一般地误解了这些东西应该如何工作)。

谁有错?我该怎么解决呢?

工作上

代码语言:javascript
复制
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)

失败继续

代码语言:javascript
复制
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)
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-03-26 19:15:21

正如内森所显示的,我对指针生命周期的假设是标准正确的。

删除者并没有被引用,这似乎是GCC或libstdc++的错误,考虑到链接的评论解决了这个问题,症状似乎相似,而且在GCC 4.8.5之前就已经修复了,这可能是bug 60367的错误。

= {}代替= FooPtr{}似乎是一个可行的解决办法。

注意,在类似的情况下,也有可能导致不良行为的7.2中的回归和一些更老的"8.0“主干构建 (谢谢阿恩·沃格尔!)。

票数 4
EN

Stack Overflow用户

发布于 2018-03-26 18:44:13

应该在bar返回时或在调用bar的完整表达式的末尾调用析构函数。

如果我们查看expr.all/4 (C++17草案),我们有

当一个函数被调用时,每个参数(11.3.5)都应该初始化(11.6,15.8,15.1)及其对应的argument....It -定义参数的生存期是在定义它的函数返回时还是在封闭的全表达式结束时.

因此,应该在函数开始时将p初始化为空FooPtr,移动指定的MakeFoo返回,然后在bar末尾或bar返回main之后最终销毁(依次调用删除器)。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49498090

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档