std :: initializer_list底层数组的生命周期是多少?

时间:2015-03-16 12:43:02

标签: c++ debugging release initializer-list

按照此回答https://stackoverflow.com/a/29074955/1098041

我有一种好奇的行为。

在Debug中我获得了预期的输出,但是在发布中(我在windows上使用mingw)我在test函数中得到了垃圾。

#include <iostream>
#include <initializer_list>

template <class T>
struct array
{
    T     *ptr;
    size_t len;

    array() { clear(); }
    array( T *p, size_t l ) { assign(p,l); }

    inline void clear() { ptr=nullptr; len=0; }
    inline void assign( T *p, size_t l ) { ptr=p; len=l; }

    inline T& operator[] ( size_t i ) const { return ptr[i]; }
};

template <class T>
inline array<const T> wrap( std::initializer_list<T> lst )
    { return array<const T>( lst.begin(), lst.size() ); }


void test( int a, int b, int c )
{
    auto ar = wrap({a,b,c});
    std::cout<< ar[1] << std::endl;
}

int main()
{
    auto a = wrap({1,2,3});
    std::cout<< a[2] << std::endl;

    test(1,2,3);
}

调试输出:

3
3

发布中的输出:

3
2686868 // some garbage.

有人可以向我解释调试/发布模式如何影响initializer_list底层数组的生命周期吗? 或者为此行为提供其他一些解释。

1 个答案:

答案 0 :(得分:2)

  auto a = wrap({1,2,3});

initializer_list(及其基础数组)的生命周期在该表达式的末尾结束,因此a包含悬空指针。

这意味着std::cout<< a[2]具有未定义的行为。类似地,对于test中的代码,std::cout << a [1]`也是未定义的行为。

  

有人可以向我解释调试/发布模式如何影响initializer_list底层数组的生命周期吗?或者为此行为提供其他一些解释。

它未定义的行为。

任何事情都可能发生。

在发布模式下,编译器以不同的方式优化事物,因此堆栈上的变量布局是不同的,因此具有未定义行为的代码可能会做一些不同的事情。或者它可能不会。

这甚至不是initializer_list特有的,您为任何临时对象获得了类似的未定义行为,您可以将其保留在指针中:

wrap( std::vector<int>(1, 1) );