English 中文(简体)
std:: 矢量推回和类构建器未被调用吗?
原标题:std::vector push_back and class constructor not being called?
  • 时间:2012-05-26 09:05:09
  •  标签:
  • c++
  • vector

我有这样的课

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:: victor like this:

stack.push_back(variable(0));

我期望变量的毁灭器将被调用,但如果在指定输入某个值之前不输入,则在指定输入某个值之前,由于我期望当实例被复制到矢量中时,会调用我提供的构建器。但出于某种原因,它不会被调用。

在调用堆叠. push_ back back the devior (option?) 之后, 毁灭器( 复制件?) 被运行, 类型有随机值, 比如, 构建器从未被调用 。

我似乎无法理解我做错了什么 请救救我!

编辑:

Ok这里是一个自我包含的示例 来显示我的意思:

#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;
}

方案以上产出如下:

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.
最佳回答

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

编辑 : < code> victor 中的实际值根本无法变异。 只有中间变量 < code > evilable(0) 才能变异。 < code> < victor 中的对象仍必须像往常一样构建和销毁。 这些规则仅适用于临时规则 。

编辑 : 为什么你要写自己的资源管理类? 您只需用自定义的删除器使用 unique_ ptr 即可。 您自己的 RTTI 也可以使用吗?

每个被摧毁的天体都已经建成。 标准中没有任何规则违反这一点。 RVO 和 NRVO 只有在您开始的时候才会产生问题, 例如, 修改您的构造器/ 毁灭器中的全局。 其它的, 它们不会影响程序的正确性 。 这就是为什么它们要重写标准。 您必须做其他错误的事情 。

最终,我不确定WTF到底发生在你身上 以及为什么它不起作用 或什么是“工作”

编辑 : 根据您的 SSCE, 那么 < em> 绝对没有出错 。 这是完全预期的行为 。 您没有遵守三者规则, 也就是说, 您摧毁了毁灭器中的资源, 但是没有努力确保您实际 < 拥有 < em > 有关资源 。 您的编译器生成的复制构建器正在破坏您的逻辑 。 您必须阅读 C++ 中处理资源时的三者规则、 复制和交换以及相似的 idom, 最好使用一个智能的指针, 这个指针已被作为标准提供, 如没有这些问题的 : < code>unique_ ptr < /code > 。

毕竟, 您在堆叠上创建了 6 个 < code> 变量 实例 - 3 个变数, 在矢量中创建了 3 个变数 。 所有的这些变数都有它们的毁灭器被调用 。 问题在于您从未考虑过复制操作, 或复制操作会做什么, 或者这些变数会发生什么( 提示: 它们会被摧毁 ) 。

考虑同样的例子

int main()
{
    variable v(0);
    push_int(v);
    variable v2 = v;
    return 0;
}

变量 < code> v 已经构建, 并分配了一个新的 < code> < int , 并且一切都是dandy。 但是, 等待 - 然后我们将它复制到 < code> v2 。 编译者生成的构建器复制了上面所有的位数。 然后, < code> v2 和 < code> 都被销毁了, 但是它们都指向同一个资源, 因为它们都持有相同的指针。 双重删除限制 。

您必须定义副本( 共享所有权 - std:: 共享_ ptr ) 或移动( 独有所有权 - std:: unique_ ptr ) 语义 。

编辑 : 只需简短的注意。 我观察到您实际上不会将 < code> push 输入到项目中, 直到它们已经返回到矢量中。 但是, 当矢量在添加额外元素时必须调整其大小, 而根本原因是一样的时, 也会观察到同样的效果 。

毁灭器被调用6次。 A 构建器被调用6次。但并非您想要的。

问题回答

Ok. 我读了更多关于不同容器的内在特性的文献,显然,我在这里要完成的工作就是“坚固”的:deque 。





相关问题
Undefined reference

I m getting this linker error. I know a way around it, but it s bugging me because another part of the project s linking fine and it s designed almost identically. First, I have namespace LCD. Then I ...

C++ Equivalent of Tidy

Is there an equivalent to tidy for HTML code for C++? I have searched on the internet, but I find nothing but C++ wrappers for tidy, etc... I think the keyword tidy is what has me hung up. I am ...

Template Classes in C++ ... a required skill set?

I m new to C++ and am wondering how much time I should invest in learning how to implement template classes. Are they widely used in industry, or is this something I should move through quickly?

Print possible strings created from a Number

Given a 10 digit Telephone Number, we have to print all possible strings created from that. The mapping of the numbers is the one as exactly on a phone s keypad. i.e. for 1,0-> No Letter for 2->...

typedef ing STL wstring

Why is it when i do the following i get errors when relating to with wchar_t? namespace Foo { typedef std::wstring String; } Now i declare all my strings as Foo::String through out the program, ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

Window iconification status via Xlib

Is it possible to check with the means of pure X11/Xlib only whether the given window is iconified/minimized, and, if it is, how?

热门标签