【问题标题】:Is STL Vector calling a destructor of a not-allocated object?STL Vector 是否调用了未分配对象的析构函数?
【发布时间】:2011-09-23 20:34:20
【问题描述】:

以下代码显示了预期之外的输出:

class test
{
    public:
    test()
    {
        std::cout << "Created" << (long)this << std::endl;
    }
    ~test()
    {
        std::cout << "Destroyed" << (long)this << std::endl;
    }
};

int main(int argc, char** argv)
{
    std::vector<test> v;
    test t;
    v.push_back(t);

    return EXIT_SUCCESS;
}

执行时显示:

Created-1077942161
Destroyed-1077942161
Destroyed674242816

我认为第二个“Destroyed”输出不应该存在。当我不使用向量时,结果是一条 Created 和一条 Destroyed 线,正如预期的那样。这种行为正常吗?

(这是在 FreeBSD 系统上使用 GCC 编译的)

【问题讨论】:

  • SSCCE+1
  • 要打印指针,最好转换为 void 指针:std::cout &lt;&lt; (void*)this &lt;&lt; std::endl;.
  • 返回EXIT_SUCCESS 也是可选的。您可以省略main 中的返回值,它将返回0(这将变成您的平台表示“正常终止”的任何数字)
  • 这很好。正在调用提供 test(const test&amp;); 的编译器。

标签: c++ stl vector


【解决方案1】:

一切都应该是这样:有局部变量t,它在main() 的末尾被创建然后销毁,还有v[0],它在main() 的末尾被创建和销毁.

您看不到 v[0] 的创建,因为这是通过复制或移动构造函数发生的,而您的测试类没有提供这些构造函数。 (所以编译器为你提供了一个,但没有输出。)


出于测试目的,为自己编写一个包含所有可能的构造函数、析构函数、赋值和交换运算符的测试类很方便,并在每个测试类中打印一条诊断行,这样您就可以看到对象在使用时的行为方式容器和算法。

【讨论】:

  • 不能是move constructor
  • @Namaz:对。要使用移动构造函数,您必须说 eitehr v.push_back(std::move(t))v.push_back(test())。不过,两者都会创建类似的消息序列。
【解决方案2】:
#include <cstdlib>
#include <vector>
#include <iostream>

class test
{
    public:
    test()
    {
        std::cout << "Created " << (long)this << std::endl;
    }
    test( const test& )
    {
        std::cout << "Copied " << (long)this << std::endl;
    }
    ~test()
    {
        std::cout << "Destroyed " << (long)this << std::endl;
    }
};

int main(int argc, char** argv)
{
    std::vector<test> v;
    test t;
    v.push_back(t);

    return EXIT_SUCCESS;
}

输出:

Created -1076546929
Copied 147865608
Destroyed -1076546929
Destroyed 147865608

std::vector::push_back复制t对象,可以看到上面的代码调用了复制构造函数。

【讨论】:

    【解决方案3】:

    向量持有t 的副本,因此在调用push_back 之后,您有两个版本的t ... 一个在堆栈上,一个在向量中。由于矢量版本是由复制构造器创建的,因此您看不到该对象的“已创建...”提示...但是当矢量容器超出范围时它仍然必须被销毁,因此您会得到两个“已销毁……”消息。

    【讨论】:

      猜你喜欢
      • 2012-03-15
      • 2018-10-25
      • 1970-01-01
      • 2017-06-11
      • 2015-12-28
      • 2012-04-29
      • 1970-01-01
      • 2020-04-29
      • 2010-11-24
      相关资源
      最近更新 更多