为什么第一个元素被破坏?

时间:2013-11-02 23:13:56

标签: c++ visual-studio-2013

我有一段这样的代码:

class Data
{
    public:
        Data(const std::vector<int> &_data)
        {
            my_data = _data;
        }

    private:
        std::vector<int> my_data;
};


int main()
{
    std::vector<std::shared_ptr<Data>> vec = {
        std::shared_ptr<Data>(new Data(std::vector<int>({ 1, 2 ,3 }))),
        std::shared_ptr<Data>(new Data(std::vector<int>({ 3, 4 ,5 })))
    };

    // breakpoint

    return 0;
}

当我暂停程序以检查值(在断点处)时,第一个(vec[0])元素被销毁而第二个元素(vec[1])正常。这里发生了什么?这是编译器中的错误吗?我正在使用新的Visual Studio 2013。

4 个答案:

答案 0 :(得分:5)

VS2013中的错误会导致对initializer_list的第一项进行双重删除。 这是流程:

  1. 构建了initializer_list。
  2. 目标向量保留为1,第一项被复制(通过复制构造函数)。
  3. vector缓慢增长到initializer_list大小。
  4. initializer_list通过vector-destructor(即delete[])销毁。最后一个元素首先被销毁。
  5. 第一个元素通过标量析构函数(即delete)再次销毁。
  6. 我在另一篇文章中看过这个,并使用调试器验证了行为。 见here

    对于VS2013,initializer_list仅适用于基本类型。

答案 1 :(得分:0)

我想共享指针注意到共享指针对象将被销毁 拥有该对象的最后剩余的shared_ptr将被销毁。 拥有该对象的最后一个shared_ptr通过operator =或reset()分配另一个指针。 我希望这有帮助

答案 2 :(得分:0)

我没有VS2013,所以我在Windows中检查MinGW 4.7中的代码,我没有发现上面提到的问题。当我在该断点处停止时,第一个(vec [0])元素和第二个(vec [0])元素都不会被销毁。

所以我猜这个问题的原因是你在那个断点处写了一些简单的代码,vs的编译器优化它,所以你在两个元素的析构函数之间准确地停在一个奇怪的地方。

您可以发布上面的反汇编代码,我们可以明确地识别问题。 :)

答案 3 :(得分:0)

这可能是编译器中的一个错误。如果你向Data构造函数和析构函数添加一些日志记录,那么你会看到它正在发生。

std::cout << __FUNCTION << ":" << this << std::endl;

我在Visual Studio 2013中确认了该问题。在“clang”下,此代码的行为符合预期。