<small id='gUWgJ'></small><noframes id='gUWgJ'>

    <tfoot id='gUWgJ'></tfoot>
  1. <legend id='gUWgJ'><style id='gUWgJ'><dir id='gUWgJ'><q id='gUWgJ'></q></dir></style></legend>
    <i id='gUWgJ'><tr id='gUWgJ'><dt id='gUWgJ'><q id='gUWgJ'><span id='gUWgJ'><b id='gUWgJ'><form id='gUWgJ'><ins id='gUWgJ'></ins><ul id='gUWgJ'></ul><sub id='gUWgJ'></sub></form><legend id='gUWgJ'></legend><bdo id='gUWgJ'><pre id='gUWgJ'><center id='gUWgJ'></center></pre></bdo></b><th id='gUWgJ'></th></span></q></dt></tr></i><div id='gUWgJ'><tfoot id='gUWgJ'></tfoot><dl id='gUWgJ'><fieldset id='gUWgJ'></fieldset></dl></div>

        <bdo id='gUWgJ'></bdo><ul id='gUWgJ'></ul>

      初始化程序列表与 2013 中的双重删除

      时间:2023-10-06

          <bdo id='I3JnL'></bdo><ul id='I3JnL'></ul>
        • <legend id='I3JnL'><style id='I3JnL'><dir id='I3JnL'><q id='I3JnL'></q></dir></style></legend>

              • <i id='I3JnL'><tr id='I3JnL'><dt id='I3JnL'><q id='I3JnL'><span id='I3JnL'><b id='I3JnL'><form id='I3JnL'><ins id='I3JnL'></ins><ul id='I3JnL'></ul><sub id='I3JnL'></sub></form><legend id='I3JnL'></legend><bdo id='I3JnL'><pre id='I3JnL'><center id='I3JnL'></center></pre></bdo></b><th id='I3JnL'></th></span></q></dt></tr></i><div id='I3JnL'><tfoot id='I3JnL'></tfoot><dl id='I3JnL'><fieldset id='I3JnL'></fieldset></dl></div>
                  <tbody id='I3JnL'></tbody>
                <tfoot id='I3JnL'></tfoot>

                <small id='I3JnL'></small><noframes id='I3JnL'>

                本文介绍了初始化程序列表与 2013 中的双重删除的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

                问题描述

                今天在我的项目中遇到内存问题,一个类使用 c++ 11 initializer_list.系统发出内存问题信号:dbgdel.cpp 中的表达式 _BLOCK_TYPE_IS_VALID(pHead->nBlockUse).我将代码简化为一个简单示例,它不再抛出表达式,但问题从调试输出中变得明显.在我看来,这代码是正确的,它似乎也适用于 g++.

                #include #include <内存>#include <字符串>#include #include <向量>#include <地图>#include #include <initializer_list>使用命名空间标准;B类{上市:字符数据[256];B(const string& x) {cout<<初始化"<<这<<结束;}B(const B& b) {cout<<复制"<<这<<结束;}~B() {cout<<删除 b" <<这<<结束;}};C类{上市:向量 Bbs;C(initializer_list<B> bb) {for(auto& b : bb) {bs.push_back(b);}}};int main(int argc, char** argv) {C bb { B("foo"), B("bar") };返回0;}

                输出为:

                <前>初始化 00B7FAE8初始化 00B7FBE8复制 00E108A0复制 00E10AE8 (?????)删除 b 00E108A0复制 00E10BE8删除 b 00B7FBE8删除 b 00B7FAE8删除 b 00B7FAE8(删除两次!)

                我在这里犯了什么错误或者这不应该工作?

                解决方案

                initializer_list 的行为有问题.在其析构函数中,它调用整个范围的向量删除(delete[]),然后再次删除数组中的第一个条目.此行为不是 initializer_list 类的一部分,看起来像是编译器错误.initializer_list 没有析构函数,也不分配用于列表的数组.它看起来就像一个 C 数组的包装器.

                至于使用您看到的额外副本,这是由向量在初始化期间调整大小引起的.这是您的流程:

                Init 00B7FAE8//构造foo"Init 00B7FBE8//构造bar"Copy 00E108A0//将foo"复制到向量(容量=1)Copy 00E10AE8 (?????)//将上述对象复制到调整大小的向量(容量 = 2)Deleting b 00E108A0//删除较小的向量缓冲区Copy 00E10BE8//将bar"从初始化列表复制到向量删除 b 00B7FBE8//以相反的顺序删除初始化列表.这是酒吧"删除 b 00B7FAE8//最后删除.这是foo"删除 b 00B7FAE8(错误)//后来 C::bs 被销毁

                您在这里可以看到,由于复制,通过 push_back 初始化向量的速度非常慢.即使您使用了更优雅的方式,也会发生这种情况:

                C(initializer_list bb) : bs(bb) {}

                一种更快(没有额外副本)的方法是:

                C(initializer_list bb) {bs.reserve(bb.size());bs.insert(bs.end(), bb.begin(), bb.end());}

                Today in run into a memory problem in my project, with a class using c++ 11 initializer_list. The system signals a memory problem: "Expression _BLOCK_TYPE_IS_VALID(pHead->nBlockUse) in dbgdel.cpp. I simplified the code to a simple example, it no longer throws an expression but the problem becomes apparent from the debug output. In my eyes this code is correct, also it seems to work with g++.

                #include <functional>
                #include <memory>
                #include <string>
                #include <iostream>
                #include <vector>
                #include <map>
                #include <sstream>
                
                #include <initializer_list>
                
                using namespace std;
                
                class B {
                public:
                    char data[256];
                    B(const string& x) {
                        cout << "Init " << this << endl;
                    }
                    B(const B& b) {
                        cout << "Copy " << this << endl;
                    }
                    ~B() {
                        cout << "Deleting b " << this << endl;
                    }
                };
                
                class C {
                public:
                    vector<B> bs;
                
                    C(initializer_list<B> bb) {
                        for(auto& b : bb) {
                            bs.push_back(b);
                        }
                    }
                };
                
                int main(int argc, char** argv) {
                    C bb { B("foo"), B("bar") };
                    return 0;
                }
                

                The output is:

                Init 00B7FAE8
                Init 00B7FBE8
                Copy 00E108A0
                Copy 00E10AE8 (?????)
                Deleting b 00E108A0
                Copy 00E10BE8
                Deleting b 00B7FBE8
                Deleting b 00B7FAE8
                Deleting b 00B7FAE8  (Deleted twice!)
                

                What mistake I make here or is this not supposed to work?

                解决方案

                The initializer_list behavior is buggy. In its destructor it calls a vector delete (a delete[]) of the entire range and then deletes the first entry in the array again. This behavior is not part of the initializer_list class and looks like a compiler bug. initializer_list doesn't have a destructor and doesn't allocate the array used for the list. It just looks like a wrapper for a C array.

                As for using the extra copy you see, it's caused by the vector resizing from during its initialization. Here's your flow:

                Init 00B7FAE8       // construct "foo"
                Init 00B7FBE8       // construct "bar"
                Copy 00E108A0       // copy "foo" to vector (capacity=1)
                Copy 00E10AE8 (?????) // copy the above object to the resized vector (capacity = 2)
                Deleting b 00E108A0   // delete the smaller vector buffer
                Copy 00E10BE8         // copy "bar" from initialization_list to vector
                
                Deleting b 00B7FBE8   // delete initialization_list in reverse order. this is "bar"
                Deleting b 00B7FAE8   // last to delete. this is "foo"
                
                Deleting b 00B7FAE8  (bug)
                
                // later C::bs is destroyed
                

                What you can see here is the initializing a vector via push_back is quite slow due to copying. This would be happen even if you've used the more elegant way:

                C(initializer_list<B> bb) : bs(bb) {}
                

                A faster (no extra copies) method is:

                C(initializer_list<B> bb) {
                    bs.reserve(bb.size());
                    bs.insert(bs.end(), bb.begin(), bb.end());
                }
                

                这篇关于初始化程序列表与 2013 中的双重删除的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持html5模板网!

                    <tbody id='YOfR1'></tbody>
                  <i id='YOfR1'><tr id='YOfR1'><dt id='YOfR1'><q id='YOfR1'><span id='YOfR1'><b id='YOfR1'><form id='YOfR1'><ins id='YOfR1'></ins><ul id='YOfR1'></ul><sub id='YOfR1'></sub></form><legend id='YOfR1'></legend><bdo id='YOfR1'><pre id='YOfR1'><center id='YOfR1'></center></pre></bdo></b><th id='YOfR1'></th></span></q></dt></tr></i><div id='YOfR1'><tfoot id='YOfR1'></tfoot><dl id='YOfR1'><fieldset id='YOfR1'></fieldset></dl></div>
                  • <bdo id='YOfR1'></bdo><ul id='YOfR1'></ul>
                      <tfoot id='YOfR1'></tfoot>

                      • <small id='YOfR1'></small><noframes id='YOfR1'>

                        1. <legend id='YOfR1'><style id='YOfR1'><dir id='YOfR1'><q id='YOfR1'></q></dir></style></legend>