使用std :: distance初始化const成员有时会出错

时间:2015-12-09 19:21:41

标签: c++ arrays stl visual-studio-2015

我对刚遇到的错误感到有些困惑。我正在使用Visual Studio 2015,我遇到了不一致的行为。我已经从它所在的项目中删除了代码并重新创建了行为,请允许我引导您完成代码:

template <typename Ty>
struct Simple_Array
{
    Ty* data;
    const size_t size;

    Simple_Array(size_t size) :
        size(size),
        data(new Ty[size])
    {
    }

    virtual ~Simple_Array() {
        delete[] data;
    }
};

正如你所看到我在我的代码中使用一个简单的c数组包装器,我想使用一个c数组来进行自学,因此不使用像std :: vector或std :: array这样的东西。使用这个时,我发现需要一个构造函数,它将第一个和最后一个迭代器放在任何其他容器上,所以我决定使用std :: distance(first,last)来计算大小。

    template <class It>
    Simple_Array(It first, It last) :
        size(std::distance(first, last)),
        data(new Ty[size])
    {
        for (int i = 0; first != last; ++first, ++i)
            data[i] = *first;
    }

现在,当我使用这个构造函数时,大小被初始化为疯狂的大值,例如3435973836.为什么?这特别令人困惑,因为以下代码可以正常工作:

    template <class It>
    Simple_Array(It first, It last) :
        Simple_Array(std::distance(first, last))
    {
        for (int i = 0; first != last; ++first, ++i)
            data[i] = *first;
    }

为了测试这个,我编写了以下主要功能:

int main() {
    auto list = { 1, 2, 3, 4 };

    try {
        Simple_Array<int>(list.begin(), list.end());
    }
    catch (...) {
        std::cout << "Failed." << std::endl;
    }

    std::cin.get();

    return 0;
}

我看了一下反汇编,但我还没弄清楚问题是什么。好消息是因为我有一个解决方法,我不需要回答这个问题来继续我的项目,但我仍然非常想知道这里出了什么问题。

我在这里粘贴了整个文件:pastebin.com/ebNrsLaB

2 个答案:

答案 0 :(得分:3)

哇!这是我生命中第一次看到臭名昭着的关于初始化顺序的gcc警告。

特别是,类成员按照它们在类中定义的顺序进行初始化,而不是按照它们在构造函数初始化列表中列出的顺序进行初始化。由于您的Ty* data;是在size之前定义的,因此在将大小设置为实际值之前对其进行初始化(已分配) - 使用未初始化大小的随机值。

要解决此问题,请确保在类中的数据之前定义大小。

答案 1 :(得分:1)

struct Simple_Array
{
    Ty* data;            // (1)
    const size_t size;   // (2)

    Simple_Array(size_t size) :
        size(size),         // (2)
        data(new Ty[size])  // (1)
    {
    }

成员变量按照它们在结构中声明的顺序进行初始化,按照在构造函数初始化列表中编写它们的顺序进行初始化。

编译器应该警告你。