是 back_insert_iterator<>按值传递安全吗?

发布于 2024-08-27 15:47:57 字数 1676 浏览 4 评论 0 原文

我有一个看起来像这样的代码:

struct Data { int value; };
class A {
public:
    typedef std::deque<boost::shared_ptr<Data> > TList;
    std::back_insert_iterator<TList> GetInserter()
    {
        return std::back_inserter(m_List);
    }
private:
    TList m_List;
};
class AA {
    boost::scoped_ptr<A> m_a;
public:
    AA() : m_a(new A()) {}
    std::back_insert_iterator<A::TList> GetDataInserter()
    {
        return m_a->GetInserter();
    }        
};
class B {
    template<class OutIt>
    CopyInterestingDataTo(OutIt outIt)
    {
        // loop and check conditions for interesting data
        // for every `it` in a Container<Data*>
        // create a copy and store it
        for( ... it = ..; .. ; ..) if (...) {
            *outIt = OutIt::container_type::value_type(new Data(**it));
            outIt++; // dummy
        }
    }
    void func()
    {
        AA aa;
        CopyInterestingDataTo(aa.GetDataInserter());
        // aa.m_a->m_List is empty!
    }
};

问题是,即使在调用 CopyInterestingDataTo() 后,A::m_List 也始终为空。但是,如果我调试并进入 CopyInterestingDataTo(),迭代器确实会存储所谓插入的数据!

更新: 我找到了罪魁祸首。我实际上有这样的想法:

class AA {
    boost::scoped_ptr<A> m_a;
    std::back_insert_iterator<A::TList> GetDataInserter()
    {
        //return m_a->GetInserter(); // wrong
        return m_A->GetInserter(); // this is the one I actually want
    }        
    // ..... somewhere at the end of the file
    boost::scoped_ptr<A> m_A;
};

现在,我应该将哪个答案标记为答案? 对于那些没有被选中的人真的很抱歉,但是你们肯定得到了一些赞成票:)

I have a code that looks something like:

struct Data { int value; };
class A {
public:
    typedef std::deque<boost::shared_ptr<Data> > TList;
    std::back_insert_iterator<TList> GetInserter()
    {
        return std::back_inserter(m_List);
    }
private:
    TList m_List;
};
class AA {
    boost::scoped_ptr<A> m_a;
public:
    AA() : m_a(new A()) {}
    std::back_insert_iterator<A::TList> GetDataInserter()
    {
        return m_a->GetInserter();
    }        
};
class B {
    template<class OutIt>
    CopyInterestingDataTo(OutIt outIt)
    {
        // loop and check conditions for interesting data
        // for every `it` in a Container<Data*>
        // create a copy and store it
        for( ... it = ..; .. ; ..) if (...) {
            *outIt = OutIt::container_type::value_type(new Data(**it));
            outIt++; // dummy
        }
    }
    void func()
    {
        AA aa;
        CopyInterestingDataTo(aa.GetDataInserter());
        // aa.m_a->m_List is empty!
    }
};

The problem is that A::m_List is always empty even after CopyInterestingDataTo() is called. However, if I debug and step into CopyInterestingDataTo(), the iterator does store the supposedly inserted data!

update:
I found the culprit. I actually have something like:

class AA {
    boost::scoped_ptr<A> m_a;
    std::back_insert_iterator<A::TList> GetDataInserter()
    {
        //return m_a->GetInserter(); // wrong
        return m_A->GetInserter(); // this is the one I actually want
    }        
    // ..... somewhere at the end of the file
    boost::scoped_ptr<A> m_A;
};

Now, which answer should I mark as answer?
Really sorry for those not chosen, but you guys definitely got some up-votes : )

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

一片旧的回忆 2024-09-03 15:47:57

简短的回答是肯定的,back_insert_iterator 可以安全地按值传递。长答案:来自标准 24.4.2/3:

插入迭代器满足
输出迭代器的要求。

和24.1.2/1

A类或内置类型X满足
输出迭代器的要求
如果 X 是可分配类型 (23.1) ...

最后来自 23.1 中的表 64:

表达式 t = u
返回类型 T&
后置条件 t 相当于 u

编辑: 乍一看,您的代码对我来说没问题,您是否 100% 确定元素确实被插入?如果您是,我将单步执行代码并检查 aa.m_a->m_List 对象的地址,并将其与 outIt 中存储的地址进行比较>CopyInterestingDataTo,如果它们不相同,则有些可疑。

The short answer is yes, back_insert_iterator is safe to pass by value. The long answer: From standard 24.4.2/3:

Insert iterators satisfy the
requirements of output iterators.

And 24.1.2/1

A class or a built-in type X satisfies
the requirements of an output iterator
if X is an Assignable type (23.1) ...

And finally from Table 64 in 23.1:

expression t = u
return-type T&
post-condition t is equivalent to u

EDIT: At a glance your code looks OK to me, are you 100% certain that elements are actually being inserted? If you are I would single step through the code and check the address of the aa.m_a->m_List object and compare it to the one stored in outIt in CopyInterestingDataTo, if they're not the same something's fishy.

青巷忧颜 2024-09-03 15:47:57

以下代码编译后打印“1”,表示已将一项添加到列表中:

#include <iostream>
#include <deque>
#include "boost/shared_ptr.hpp"
#include "boost/scoped_ptr.hpp"

struct Data { 
    int value; 
    Data( int n ) : value(n) {}
};

struct A {
    typedef std::deque<boost::shared_ptr<Data> > TList;
    std::back_insert_iterator<TList> GetInserter()
    {
        return std::back_inserter(m_List);
    }
    TList m_List;
};

struct AA {
    boost::scoped_ptr<A> m_a;
    AA() : m_a(new A()) {}
    std::back_insert_iterator<A::TList> GetDataInserter()
    {
        return m_a->GetInserter();
    }        
};

struct B {
    template<class OutIt>
    void CopyInterestingDataTo(OutIt outIt)
    {
        *outIt = typename OutIt::container_type::value_type(new Data(0));
        outIt++; // dummy
    }
    int func()
    {
        AA aa;
        CopyInterestingDataTo(aa.GetDataInserter());
        return aa.m_a->m_List.size();
    }
};

int main() {
    B b;
    int n = b.func();    
    std::cout <<  n << std::endl;
}

The following code, which compiles, prints "1", indicating one item added to the list:

#include <iostream>
#include <deque>
#include "boost/shared_ptr.hpp"
#include "boost/scoped_ptr.hpp"

struct Data { 
    int value; 
    Data( int n ) : value(n) {}
};

struct A {
    typedef std::deque<boost::shared_ptr<Data> > TList;
    std::back_insert_iterator<TList> GetInserter()
    {
        return std::back_inserter(m_List);
    }
    TList m_List;
};

struct AA {
    boost::scoped_ptr<A> m_a;
    AA() : m_a(new A()) {}
    std::back_insert_iterator<A::TList> GetDataInserter()
    {
        return m_a->GetInserter();
    }        
};

struct B {
    template<class OutIt>
    void CopyInterestingDataTo(OutIt outIt)
    {
        *outIt = typename OutIt::container_type::value_type(new Data(0));
        outIt++; // dummy
    }
    int func()
    {
        AA aa;
        CopyInterestingDataTo(aa.GetDataInserter());
        return aa.m_a->m_List.size();
    }
};

int main() {
    B b;
    int n = b.func();    
    std::cout <<  n << std::endl;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文