4

我正在尝试使用函数模板foo将参数转换为initializer_list. 但是,initializer_list它转换的值具有与输入参数不同的奇怪值。

#include <iostream>
#include <iterator>
#include <string>
#include <vector>

using namespace std;

template<class T>
void func(std::initializer_list<T> a_args)
{
    if (a_args.begin() != a_args.end())
    {
        auto last = prev(a_args.end());
        copy(a_args.begin(), last, ostream_iterator<int>(cout, ","));
        cout << *last;
    }
    cout << endl;
}

template<class T, class ...Args>
struct first_of
{
    typedef T type;
};

template<class ...Args>
initializer_list<typename first_of<Args...>::type> foo(Args&&... args)
{
    return { forward<Args>(args)... };
}

int main()
{
    func({1,2,3});
    auto x = foo(1,2,3);
    func(x); //this should be the same as func({1,2,3}) but not.
}

实时代码

输出如下:

1,2,3
-326483696,32767,0

这里有什么问题?

4

1 回答 1

7

std::initializer_list<T> should only be used as a temporary object or function parameter, since it refers to a temporary array.

8.5.4/5-6:

An object of type std::initializer_list<E> is constructed from an initializer list as if the implementation allocated a temporary array of N elements of type const E, where N is the number of elements in the initializer list. ...

The array has the same lifetime as any other temporary object (12.2), except that initializing an initializer_list object from the array extends the lifetime of the array exactly like binding a reference to a temporary.

18.9/2:

An object of type initializer_list<E> provides access to an array of objects of type const E. [Note: A pair of pointers or a pointer plus a length would be obvious representations for initializer_list. initializer_list is used to implement initializer lists as specified in 8.5.4. Copying an initializer list does not copy the underlying elements.]

So returning an initializer_list object is just as bad as:

struct int_ref {
    int& ref;
    explicit constexpr int_ref(int& r) : ref(r) {}
};

int_ref func() {
    int n = 5;
    return int_ref(n);
}
于 2013-09-28T12:57:16.403 回答