简体   繁体   English

C ++,如何从迭代器返回对成员变量的引用

[英]C++ , how to return a reference to the member variable from iterator

There is the following class B derived from std::vector 从std :: vector派生以下B类

class B: public std::vector <unsigned int>
{
    public:
            B() : std::vector <unsigned int> ( 0 ) {}
};

and a class A witten as follows: 和A级机智如下:

class A
{
    private:        
            B b;    
    double x;

public:
    B & getB () {return b;}
    B const & getB() const {return b;}

    bool operator() ( const A & a ) const
            {
                    return a < a.x;
            }
};

Why it is impossible to return a refererence to the variable b of some object A stored in std::list from its iterator (and how to do that)? 为什么不可能从其迭代器返回对存储在std :: list中的某个对象A的变量b的引用(以及如何做到这一点)?

int main ()
{
std::set <A > alist;
std::set <A> ::iterator i_alist = alist.begin();

for (; i_alist != alist.end(); i_list++)
{
    B &il = (*i_alist).getB(); //Compiler error
    B &il2 = i_alist->getB(); //Compiler error

    il.push_back(10);   //Modify il and concurrently B
}
} 

Compiler error: 编译器错误:

Error   1   error C2440: 'initializing' : cannot convert from 'const B' to 'B &'    d:\test.cpp

Thanks for your help... 谢谢你的帮助...

Edit question : 编辑问题

The possible solution using const_cast : 使用const_cast的可能解决方案:

B &il2 = const_cast <B&> ( i_alist->getB() );

This has very little to do with std::vector and everything to do with std::set . 这与std::vector几乎没有关系,而与std::set无关。 You store your objects in a std::set . 您将对象存储在std::set Elements of std::set are not modifiable from the outside. std::set元素不能从外部修改。 Once you inserted an element into a set, you cannot change it. 将元素插入集合后,就无法更改。

For this reason, std::set::iterator might (and will) evaluate to a constant object, even if it is not a const_iterator (the language specification actually allows std::set::iterator and std::set::const_iterator to refer to the same type, but does not require it). 因此,即使std::set::iterator不是const_iterator (语言规范实际上允许std::set::iteratorstd::set::const_iterator也可能),并且std::set::iterator可能(并且将)评估为常量对象。以指代相同类型,但不需要)。 Ie in your example *i_list is a const-qualified object of type const A . 即在您的示例中*i_list是类型为const A的const限定对象。 The compiler will call the const version of getB , which returns const B & . 编译器将调用getBconst版本,该版本返回const B & You are apparently hoping to break through that constness, expecting the non-const version of getB to be called. 您显然希望突破该常量,期望调用getB的非常量版本。

There's no way around it, unless you decide to use some sort of hack ( const_cast etc.) to remove the constness from the set element and thus make the compiler to call non-const version of getB . 除非您决定使用某种技巧( const_cast等)从set元素中删除constness并因此使编译器调用getB非const版本, getB

The const_cast -based hack-solution would look as 基于const_cast的黑客解决方案看起来像

B &il = const_cast<A &>(*i_alist).getB();

or you can remove the constness later, from the returned B reference 或者您可以稍后从返回的B参考中删除常量。

B &il = const_cast<B &>((*i_alist).getB());
B &il2 = const_cast<B &>(i_alist->getB());

There are some things that look weird about your example: 关于您的示例,有些事情看起来很奇怪:

  1. Never derive from std::vector . 永远不要从std::vector派生。 It's not designed for that use. 它不是为此设计的。 And there normally is no reason to do so, except laziness, ie to avoid some typing. 通常,除了懒惰以外,没有其他理由这样做,即避免打字。
  2. What is that A::operator() for? A::operator()做什么用的? Looks like some strange way to provide a Comparator for the std::set you are using. 为您正在使用的std::set提供一个Comparator的某种奇怪方法。 Normally you don't alter a class just because you stuff it into a std::set somewhere. 通常,您不会仅仅因为std::set某个类填充到std::set而改变了一个类。 If you really want to be able to compare your A's (generally, not just for the set), then write a proper free bool operator<(A const&, A const&); 如果您真的想比较A(通常不只是针对集合),则编写一个适当的免费bool operator<(A const&, A const&); If it's just for the set, write a custom Comparator in the place where you use the set. 如果仅用于集合,请在使用集合的地方编写一个自定义比较器。 (That comparator should not need to access A's privates) (该比较器不需要访问A的私有对象)
  3. What is the A::x used for? A::x是什么? Only for comparison or even only for the comparison inside the set? 仅用于比较,甚至仅用于集合内的比较? If it's just that, consider to use a std::map<double, A> or even a std::map<double, B> where you put your x as the keys and the actual objects as the values. 如果仅仅是这样,请考虑使用std::map<double, A>或什至std::map<double, B> ,其中将x用作键,将实际对象用作值。

You see, there are a lot of open questions I ask, and maybe the solution (using a map) does not even fit your problem. 您会看到,我有很多未解决的问题,也许解决方案(使用地图)甚至不适合您的问题。 That is because you did not show us the real code you have but only some example with meaningless names. 那是因为您没有向我们展示您拥有的真实代码,而只是给我们展示了一些无意义的示例。 So we only see what you are trying to do , not what you actually want to achieve with your code. 因此,我们只看到您正在尝试执行的操作 ,而不是您实际上想要通过代码实现的操作。

PS: maybe you don't even need an ordered container in the first place, it could suffice to stuff all the objects into a std::vector and then std::sort it. PS:也许您甚至根本不需要一个有序的容器,将所有对象填充到std::vector然后std::sort Depends on the kind of objects you really have (the A's of your example are cheap to copy/swap) and of the ways you use the container - how the insertions are interleaved with the loops and so on. 取决于您实际拥有的对象的种类(示例中的A很容易复制/交换)以及使用容器的方式-插入与循环的交错方式等。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM