首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >未调用std::vector push_back和类构造函数?

未调用std::vector push_back和类构造函数?
EN

Stack Overflow用户
提问于 2012-05-26 17:05:10
回答 2查看 1.2K关注 0票数 1

我的课是这样的

代码语言:javascript
运行
复制
class variable
{
    public:
        variable(int _type=0) : type(_type), value(NULL), on_pop(NULL)
        {
        }

        virtual ~variable()
        {
            if (type)
            {
                std::cout << "Variable Deleted" <<std::endl;
                on_pop(*this);
                value=NULL;
            }
        }

        int     type;
        void*   value;
        typedef void(*func1)(variable&);
        func1 on_pop;
}

然后我将实例推入std::vector中,如下所示:

代码语言:javascript
运行
复制
stack.push_back(variable(0));

我期望调用变量的析构函数,但if不会进入,直到为type赋值,因为我期望我提供的构造函数将在实例被复制到向量中时被调用。但出于某种原因,情况并非如此。

调用stack.push_back后,析构函数(副本的?)并且type有一些随机值,就像从未调用过构造函数一样。

我似乎想不出我做错了什么。请帮帮我!^_^

编辑:

好的,这里有一个自包含的例子来说明我的意思:

代码语言:javascript
运行
复制
#include <iostream>
#include <vector>

class variable
{
    public:
        variable(int _type=0) : type(_type), value(NULL), on_pop(NULL)
        {
        }

        ~variable()
        {
            if (type)
            {
                std::cout << "Variable Deleted" <<std::endl;
                on_pop(*this);
                value=NULL;
            }
        }

        int     type;
        void*   value;

        typedef void(*func1)(variable&);
        func1 on_pop;
};

static void pop_int(variable& var)
{
    delete (int*)var.value;
}

static void push_int(variable& var)
{
    var.type = 1;
    var.value = new int;
    var.on_pop = &pop_int;
}

typedef void(*func1)(variable&);
func1 push = &push_int;

int main()
{
    std::vector<variable>   stack;

    stack.push_back(variable(0));
    push(stack[stack.size()-1]);

    stack.push_back(variable(0));
    push(stack[stack.size()-1]);

    stack.push_back(variable(0));
    push(stack[stack.size()-1]);

    return 0;
}

上面的程序输出如下:

代码语言:javascript
运行
复制
Variable Deleted
Variable Deleted
Variable Deleted
Variable Deleted
Variable Deleted
Variable Deleted

Process returned 0 (0x0)   execution time : 0.602 s
Press any key to continue.
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-05-26 17:07:26

欢迎来到RVO和NRVO。这基本上意味着,如果对象是多余的,编译器可以跳过创建对象-即使它的构造函数和析构函数有副作用。您不能依赖于立即复制或移动到实际存在的对象。

编辑:vector中的实际值根本不能省略。只能省略中间变量variable(0)vector中的对象仍然必须像往常一样构造和析构。这些规则仅适用于临时用户。

编辑:为什么要编写自己的资源管理类?您可以简单地使用带有自定义删除器的unique_ptr。你自己的RTTI呢?

每个被析构的对象都必须被构造。在标准中没有违反这一点的规则。RVO和NRVO只有在您开始时才会出现问题,例如,修改构造函数/析构函数中的全局变量。否则,它们对程序的正确性没有任何影响。这就是为什么他们是标准的。你一定是做错了什么。

归根结底,我只是不确定WTF到底发生在你身上,为什么它不工作,或者什么是“工作”。发布SSCCE。

编辑:根据你的SSCCE,绝对不会出任何问题。这完全是意料之中的行为。您没有遵守规则三-即,您销毁析构函数中的资源,但没有努力确保您实际拥有有问题的资源。编译器生成的复制构造函数正在破坏您的逻辑。您必须阅读有关C++中的三个规则、复制和交换以及类似的资源处理习惯用法,并且最好使用已经作为标准提供的智能指针,如unique_ptr,它没有这些问题。

毕竟,您创建了六个variable实例-三个在堆栈上,三个在向量内。所有这些都有自己的析构函数调用。问题是你从来没有考虑过复制操作,或者复制会做什么,或者这些临时文件会发生什么(提示:它们被销毁了)。

考虑同样的例子:

代码语言:javascript
运行
复制
int main()
{
    variable v(0);
    push_int(v);
    variable v2 = v;
    return 0;
}

变量v被构造并分配一个新的int,一切都很顺利。但是等等--然后我们把它复制到v2中。编译器生成的构造函数复制所有的位。然后v2v都会被销毁-但它们都指向相同的资源,因为它们都持有相同的指针。双删除法比比皆是。

您必须定义copy (共享所有权- std::shared_ptr)或move (唯一所有权- std::unique_ptr)语义。

编辑:只是一个简单的注释。我观察到,实际上直到项目已经在向量中之后,才会push到项目中。但是,如果在添加其他元素时必须调整向量的大小,并且基本原因是相同的,则会出现相同的效果。

析构函数被调用了6次。一个构造函数会被调用六次。只是不是你想要的那个。

票数 4
EN

Stack Overflow用户

发布于 2012-05-26 21:00:40

好的。我已经阅读了更多关于不同容器的内部特性,显然,我在这里试图完成的工作是std::deque

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10764974

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档