gpt4 book ai didi

c++ - 变量的初始化列表

转载 作者:行者123 更新时间:2023-11-30 01:49:28 25 4
gpt4 key购买 nike

是否可以创建变量的 initializer_list,例如函数参数(参见 function test)?

下面的代码有效,Clang 和 GCC 都没有提示任何事情,但我只是想确保它没问题。

#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} 将超出范围,我返回的数组将是无效 - 正确吗?

最佳答案

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

这会创建一个 int[3] 类型的临时数组, 然后绑定(bind) initializer_list<int>到那个数组,然后调用 wrap这会创建一个 array<const int>引用数组。

在表达式的末尾,数组被销毁,留下 array<const int>带有悬空指针,所以这是未定义的行为:

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

这也适用于 main 中的代码, 变量 a包含一个悬挂指针和 a[2]是未定义的行为。

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

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

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

==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:

==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)

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?

它已经超出范围并且ar甚至在您返回之前就已经无效了。

关于c++ - 变量的初始化列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29074892/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com