C++ std::initializer_list data() 函数错误

Posted

技术标签:

【中文标题】C++ std::initializer_list data() 函数错误【英文标题】:C++ std::initializer_list data() function error 【发布时间】:2014-02-20 18:03:32 【问题描述】:

我尝试为 std::initializer_list 类型创建一个基本的data() 函数以从列表中提取数据。但是,在sum(1, 2, 3, 4) 的基本求和函数中尝试它时,我得到的结果是1447450180 而不是10

template < typename _Ty > const _Ty *data(const std::initializer_list<_Ty> &_List)

    _Ty *data = new _Ty[_List.size()];
    for (typename std::initializer_list<_Ty>::iterator i = _List.begin();
                i != _List.end(); ++i, *data++ = *i);
    return data;


int sum(std::initializer_list<int> numbers)

    int total = 0;
    for(int i = 0; i < numbers.size(); ++i, total += data(numbers)[i]);
    return total;


int main()

    std::cout << sum(1, 2, 3, 4);
    getchar();

【问题讨论】:

为什么还需要数据功能呢?您似乎正试图以一种糟糕的方式混合 Java、C 和 C++11。 @LB-- 更容易而不是写int sum(std::initializer_list&lt;int&gt; numbers) int total = 0; for(typename std::initializer_list&lt;int&gt;::iterator i = numbers.begin(); i != numbers.end(); ++i) total += *i; return total; ,并允许通过索引访问元素 你并没有让它变得更容易,而是让它变得更加复杂。看起来您不太了解迭代器,而且您似乎肯定不了解如何使用初始化列表。 @LB--:我非常了解如何使用迭代器,但是,我刚刚开始使用 initalizer_lists。 @Joseph 你是否意识到对data()每次调用 都会分配内存(并泄漏它)然后复制初始化程序列表的内容?这很容易成为重新实现 std::accumulate 的最糟糕的方法 【参考方案1】:

2 个错误:

for (typename std::initializer_list<_Ty>::iterator i = _List.begin();
            i != _List.end(); ++i, *data++ = *i);

您正在递增 data 指针,它会跳过先前分配的内存。创建一个count 变量:

int count = 0;
data[count++] = *i

但是现在您正在跳过循环的第一个元素,因为您先递增然后取消引用。换个顺序。最终循环应如下所示:

    for (typename std::initializer_list<_Ty>::iterator i = _List.begin();
            i != _List.end(); data[count++] = *i, ++i);

Live Demo

【讨论】:

数据不是数组。它是一个指针。它定义为 _Ty *data @VladfromMoscow 已修复【参考方案2】:

使用简单的解决方案,而不是复杂的解决方案。

#include <numeric>
template<typename T>
T sum(std::initializer_list<T> vals)

    return std::accumulate(vals.begin(), vals.end(), T);

http://coliru.stacked-crooked.com/a/524ffb543683d901

【讨论】:

【参考方案3】:

这个功能

template < typename _Ty > const _Ty *data(const std::initializer_list<_Ty> &_List)

    _Ty *data = new _Ty[_List.size()];
    for (typename std::initializer_list<_Ty>::iterator i = _List.begin();
                i != _List.end(); ++i, *data++ = *i);
    return data;

至少是无效的,因为存在内存泄漏。每次调用该函数时,它都会为数组数据分配新的内存,并且永远不会删除该数组。

此外,该函数返回数组之外的指针,因为在其中指针已更改,即它已递增。

你也不知道如何正确地编写循环。在这个循环中,您 1) 跳过序列的第一个元素,然后 2 尝试访问序列之外的元素。

    for (typename std::initializer_list<_Ty>::iterator i = _List.begin();
                i != _List.end(); ++i, *data++ = *i);

正确的循环看起来

    for (typename std::initializer_list<_Ty>::iterator i = _List.begin();
                i != _List.end(); ++i )  *data++ = *i;

第二个循环同样有效,因为它也是无效的

for(int i = 0; i < numbers.size(); ++i, total += data(numbers)[i]);

应该有

for(int i = 0; i < numbers.size(); ++i ) total += data(numbers)[i];

我也看不出你的发明有什么意义。

【讨论】:

我先试过了,但没用,所以我在 Q 中做了循环,即使我知道这是错误的 恐怕还是不行,为了反驳I do not see any sense in your invention.,我创建了它,这样你就不必写出迭代器循环,也可以通过在data 函数上使用[] 运算符的索引 @Joseph 我创建它是为了让您不必写出迭代器循环——这正是&lt;algorithm&gt; 标头中大多数东西存在的原因!跨度>

以上是关于C++ std::initializer_list data() 函数错误的主要内容,如果未能解决你的问题,请参考以下文章

在 Visual C++ 编译器中使用 std::initializer_list 2012 年 11 月 CTP

使用 std::initializer_list 创建指向 std::min 的函数指针

为啥 `std::initializer_list` 不提供下标运算符?

为啥 std::min(std::initializer_list<T>) 按值接受参数?

为啥 std::initializer_list 不是内置语言?

std::initializer_list 作为函数参数