初始化程序变量列表

初始化程序变量列表

本文介绍了初始化程序变量列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

可以创建一个 initializer_list 的变量,例如函数参数(cf. function test ) ?下面的代码是可行的,既没有clang也没有gcc抱怨什么,但我只是想确保这是确定。

Is it possible to create an initializer_list of variables, like function arguments for example (cf. function test)? The code below works, and neither clang nor gcc complain about anything, but I would just like to make sure this is ok.

edit: wrap 的参数改为const ref

edit: changing the argument of wrap to a const ref

#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( const 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[2] << std::endl;
}

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

    test(1,2,3);
}

如果我试图在 test 中返回我的包数组,初始化列表 {a,b,c}

Side question; if I tried to return my wrapped array in test, the initializer list {a,b,c} would get out of scope, and the array I'm returning would be invalid -- is that correct?

推荐答案

 auto ar = wrap({a,b,c});

这将创建 int [3] ,然后将 initializer_list< int> 绑定到该数组,然后调用 wrap $ c> array< const int>

This create a temporary array of type int[3], then binds an initializer_list<int> to that array, then calls wrap which creates an array<const int> that refers to the array.

在表达式的末尾,数组被销毁, code> array< const int> 使用悬空指针,因此这是未定义的行为:

At the end of the expression the array is destroyed, leaving the array<const int> with a dangling pointer, so this is undefined behaviour:

 std::cout<< ar[2] << std::endl;

这也适用于 main ,变量 a 包含悬空指针, a [2] 是未定义的行为。

This also applies to the code in main, the variable a contains a dangling pointer and a[2] is undefined behaviour.

你可以通过用分配内存的类型数组替换 int 的数组来验证这一点,以便valgrind或asan注意到错误:

You can verify this by replacing the array of int with an array of types that allocate memory, so that valgrind or asan will notice the bug:

using V = std::vector<int>;
auto a = wrap({V{1}, V{2}, V{3}});
std::cout<< a[2].front() << std::endl;

现在 a [2] code> std :: vector< int> 对象,但试图访问其 front()成员导致程序中止: / p>

Now a[2] is a std::vector<int> object, but trying to access its front() member causes the program to abort:

==28356==ERROR: AddressSanitizer: heap-use-after-free on address 0x60200000efb0 at pc 0x000000401205 bp 0x7fffa46f2900 sp 0x7fffa46f28f8
READ of size 4 at 0x60200000efb0 thread T0
    #0 0x401204 in main /tmp/il.cc:28
    #1 0x3236e21d64 in __libc_start_main (/lib64/libc.so.6+0x3236e21d64)
    #2 0x400ec8  (/tmp/a.out+0x400ec8)
...

或使用valgrind:

Or with valgrind:

==28364== Invalid read of size 4
==28364==    at 0x400C72: main (il.cc:28)
==28364==  Address 0x51dfd20 is 0 bytes inside a block of size 4 free'd
==28364==    at 0x4A07991: operator delete(void*) (vg_replace_malloc.c:502)
==28364==    by 0x4013BF: __gnu_cxx::new_allocator<int>::deallocate(int*, unsigned long) (new_allocator.h:110)
==28364==    by 0x4012F8: std::allocator_traits<std::allocator<int> >::deallocate(std::allocator<int>&, int*, unsigned long) (alloc_traits.h:386)
==28364==    by 0x4011B1: std::_Vector_base<int, std::allocator<int> >::_M_deallocate(int*, unsigned long) (stl_vector.h:178)
==28364==    by 0x40102A: std::_Vector_base<int, std::allocator<int> >::~_Vector_base() (stl_vector.h:160)
==28364==    by 0x400EC4: std::vector<int, std::allocator<int> >::~vector() (stl_vector.h:425)
==28364==    by 0x400C2A: main (il.cc:27)



已经超出范围, ar 无效,甚至在您退回之前。

It's already out of scope and ar already invalid even before you return it.

这篇关于初始化程序变量列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-31 08:21