Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/155.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 初始值设定项变量列表_C++_C++11_Initializer List - Fatal编程技术网

C++ 初始值设定项变量列表

C++ 初始值设定项变量列表,c++,c++11,initializer-list,C++,C++11,Initializer List,是否可以创建变量的初始值设定项\u列表,例如函数参数(参见函数测试) 下面的代码是有效的,无论是Clang还是GCC都不会抱怨任何事情,但我只想确保这一切正常 #include <iostream> #include <initializer_list> template <class T> struct array { T *ptr; size_t len; array() { clear(); } array( T *p

是否可以创建变量的
初始值设定项\u列表
,例如函数参数(参见函数
测试

下面的代码是有效的,无论是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);
}
#包括
#包括
样板
结构体数组
{
T*ptr;
尺寸透镜;
数组(){clear();}
数组(T*p,size_T l){assign(p,l);}
内联void clear(){ptr=nullptr;len=0;}
内联void赋值(T*p,size_T l){ptr=p;len=l;}
内联T&运算符[](size_T i)常量{return ptr[i];}
};
样板
内联数组换行(常量std::初始值设定项\u list&lst)
{返回数组(lst.begin(),lst.size());}
无效测试(内部a、内部b、内部c)
{
自动ar=换行({a,b,c});
标准::cout
这将创建类型为
int[3]
的临时数组,然后将
初始值设定项列表
绑定到该数组,然后调用
wrap
,创建引用该数组的
数组

在表达式末尾,数组被销毁,留下一个悬空指针的
数组
,因此这是未定义的行为:

 std::cout<< ar[2] << std::endl;
现在,
a[2]
是一个
std::vector
对象,但试图访问其
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)
==28364==大小为4的无效读取
==28364==at 0x400C72:main(il.cc:28)
==28364==地址0x51dfd20是大小为4的块中的0字节
==28364==at 0x4A07991:运算符删除(void*)(vg_replace_malloc.c:502)
==28364==by 0x4013BF:u gnu_cxx::新的_分配器::解除分配(int*,无符号长)(新的_分配器.h:110)
==28364==by 0x4012F8:std::allocator_traits::deallocate(std::allocator&,int*,unsigned long)(alloc_traits.h:386)
==28364==0x4011B1:std::_Vector_base::_M_deallocate(int*,无符号长)(stl_Vector.h:178)
==28364==0x40102A:std::_Vector_base::~_Vector_base()(stl_Vector.h:160)
==28364==0x400EC4:std::vector::~vector()(stl_vector.h:425)
==28364==0x400C2A:main(il.cc:27)
附带问题;如果我试图在测试中返回包装好的数组,则初始化列表
{a,b,c}
将超出范围,并且我返回的数组将无效--正确吗

 auto ar = wrap({a,b,c}); 
它已经超出范围,
ar
甚至在您返回它之前就已经无效

这将创建类型为
int[3]
的临时数组,然后将
初始值设定项列表
绑定到该数组,然后调用
wrap
,创建引用该数组的
数组

在表达式末尾,数组被销毁,留下一个悬空指针的
数组
,因此这是未定义的行为:

 std::cout<< ar[2] << std::endl;
现在,
a[2]
是一个
std::vector
对象,但试图访问其
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)
==28364==大小为4的无效读取
==28364==at 0x400C72:main(il.cc:28)
==28364==地址0x51dfd20是大小为4的块中的0字节
==28364==at 0x4A07991:运算符删除(void*)(vg_replace_malloc.c:502)
==28364==by 0x4013BF:u gnu_cxx::新的_分配器::解除分配(int*,无符号长)(新的_分配器.h:110)
==28364==by 0x4012F8:std::allocator_traits::deallocate(std::allocator&,int*,unsigned long)(alloc_traits.h:386)
==28364==0x4011B1:std::_Vector_base::_M_deallocate(int*,无符号长)(stl_Vector.h:178)
==28364==0x40102A:std::_Vector_base::~_Vector_base()(stl_Vector.h:160)
==28364==0x400EC4:std::vector::~vector()(stl_vector.h:425)
==28364==0x400C2A:main(il.cc:27)
附带问题;如果我试图在测试中返回包装好的数组,则初始化列表
{a,b,c}
将超出范围,并且我返回的数组将无效--正确吗

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

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

我确实认为在模板定义中使用
inline
关键字是没有用的。我想我还记得“C++编码标准”中的内容Sutter和Alexandrescu指出,内联声明函数通常是无用的,因为这只是编译器的一个指示,而且编译器往往比您更聪明。我确实认为在模板定义中使用
inline
关键字是无用的。我想我还记得“C++编码标准”中的Sutter和Alexandrescu指出,内联声明一个函数通常是无用的,因为这只是编译器的一个指示,而且编译器往往比您更聪明。这里的关键点是,
初始值设定项所使用的临时数组的生存期仅绑定到该对象;它不会扩展到任何对象另一个注意:在这里使用
std::array
std::vector
将是非常困难的;问题的出现是因为OP的
array
持有一个不属于它的原始指针,指向它初始化时使用的任何对象;而这些标准容器将拥有自己的原始指针由初始值设定项中的值复制/移动的存储。为了澄清“在表达式末尾,数组被销毁”;这是唯一正确的,因为我的
初始值设定项\u list
本身是临时的,不是吗?通过值传递初始值设定项列表,对其进行包装,并在函数范围内使用包装值,对吗?只是为了确认我刚才所说的,将
wrap
的参数更改为常量ref,然后运行
std::coutThat'这是一种完全不同的情况,数组的生存期确实得到了延长。你没有说任何关于使用自动
初始值设定项\u list
,你一直在谈论按值传递它,所以我认为你仍然只是在谈论
f({…})形式的用法
,其中数组的生存期没有任何延长。最明显的是存在一个disti