【问题标题】:c++ operator < overloading how to use?c++运算符<重载如何使用?
【发布时间】:2013-06-02 17:44:59
【问题描述】:

我想对名为ORIGINstd::map 的值进行for 循环,如下所示,从较低的值到较高的值: 我需要重载 &lt; 运算符才能做到这一点。

myclass
{
    typedef std::vector<tactics*> origin_of_tactics;
    typedef map<float, origin_of_tactics, CompareFloat> ::iterator iter_type;
    iter_type it;
    map<float, origin_of_tactics, CompareFloat> ORIGIN;


    for (it = ORIGIN.find(low_value_in_bar); it <= ORIGIN.find(high_value_in_bar); it++)
    {

    }

} // end of myclass

我看到了一个重载运算符的示例,我尝试更改它,但我不确定如何在我的课堂上使用它。 如果它是正确的方法:

class Complex
{
    public:
        typedef std::vector<tactics*> origin_of_tactics;
        typedef map<float, origin_of_tactics, CompareFloat>::iterator iter_type;
        bool Complex::operator <(const iter_type &other);
        Complex(iter_type value) : it1(value)
        {};
        bool operator <(const Complex &other);

    private:
        iter_type it1;

};
bool Complex::operator <(const iter_type &other)
{
    if ((it1->first) < (other->first))
    {
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}

怎么做?以及如何为任何类型的 MAP 迭代器

【问题讨论】:

  • 1) 您的地图有 float 键。 2)你传递一个比较函数给它。所以你的类中不需要任何比较运算符。
  • I want to do a for loop on **values** of a std::map - 也许地图以外的数据类型更适合
  • @djf std::map 是一个排序容器,元素总是使用给定的比较运算符按索引排序。您可以简单地使用迭代器begin()end() 来迭代(排序的)元素。你有什么问题?
  • 次要:“TRUE”和“FALSE”不是布尔值,请改用“true”和“false”。
  • Major:iter_type it; 在类实例中存储迭代器很可能会让您在这个阶段对语言的理解感到痛苦,我强烈建议您不要这样做。

标签: c++ operator-overloading


【解决方案1】:

这本质上是一条注释,但我希望代码可读。

myclass
{
    typedef std::vector<tactics*> origin_of_tactics;
    typedef map<float, origin_of_tactics, CompareFloat> ::iterator iter_type;
    iter_type it;
    map<float, origin_of_tactics, CompareFloat> ORIGIN;


    for (it = ORIGIN.find(low_value_in_bar); it <= ORIGIN.find(high_value_in_bar); it++)
    {
    }
} // end of myclass

你应该先清理一下:

class myclass
{
public:
    typedef std::vector<tactics*> origin_of_tactics;
    typedef map<float, origin_of_tactics> origins;

    origins ORIGIN;
    // Do NOT store the iterator *value* as a class instance variable
    // it will burn you with fire at this stage in learning C++.
    // The typedef is a good idea for when you have to explicitly state
    // the type, especially if you don't have access to C++11s "auto".
    typedef origins::iterator origin_iter;

    // assuming you want to specify a subset of the values.
    void somefunction(float low_value_in_bar, float high_value_in_bar)
    {
        auto start = ORIGIN.lower_bound(low_value_in_bar);
        auto end   = ORIGIN.upper_bound(high_value_in_bar);
        for (auto it = start; it != end; ++it)
        {
            ....
        }
    }

    // otherwise, since you're using map and it's an ordered container
    void somefunction()
    {
        for (auto it = ORIGIN.begin(); it != ORIGIN.end(); ++it)
        {
            ....
        }
    }

    // or, using new C++11 for
        for (auto& oot : ORIGIN)
        {
           // (oot is of type origin_of_tactics)
        }
} // end of myclass

您不需要重载 operator

您问题中的代码看起来像是将迭代器保留在类成员变量中,而不是作为函数的局部变量。尽量避免这种情况(成员变量迭代器):它会咬你一口,因为迭代器是具有有限生命周期的复杂类型。将它们的定义保持在本地使用可以更容易地追踪它们变得无效的原因。始终将迭代器视为临时的和瞬态的。

std::vector<int> v = { 5, 3, 1 };
auto it = v.begin();
cout << "*it = " << *it << endl;
...
v.push_back(10);
// vector just got bigger and is no-longer in the same location,
// but "it" still points to the old location.
v[0] = 90;
cout << "*it = " << *it << endl; // probably crashes, but won't print 90.

“auto”关键字是一个新的 C++11 关键字,表示“弄清楚这对我来说应该是什么”,可用于局部变量声明:

std::map<std::string, std::vector<std::array<int, 5> > foo;
std::map<std::string, std::vector<std::array<int, 5> >::iterator it = foo.begin();

可以替换为

std::map<std::string, std::vector<std::array<int, 5> > foo;
auto it = foo.begin();

http://en.cppreference.com/w/cpp/keyword/auto

【讨论】:

  • 嗨 kfsone,1) 你为什么使用“auto”? 2)我也想在它 == ORIGIN.end() 的情况下进入循环,以防我使用 != 在 == 的情况下它不会进入循环 3)如果我不放迭代器作为类成员,我每次都需要将它们编写为例如origins::iterator,你不喜欢把迭代器写成类成员的原因是什么?,谢谢
  • typedef 非常好 - 甚至是可取的。但实际上存储它并不是因为迭代器可能变得无效。我会编辑回复来解释。
  • 我的意思是我也想进入循环内部,以防它 == ORIGIN.find(high_value_in_bar)
  • 好的 - 你问题中的代码使它看起来像迭代器被定义为类成员而不是函数局部变量:)
  • @user2162793 upper_bound 将等同于您的原始代码,因为它会在 匹配值或结束之后找到下一个迭代器,即第一个 是 >= high_bar_value。
【解决方案2】:

这是错误的:

bool Complex::operator <(const iter_type &other);
// ...
bool Complex::operator <(const iter_type &other);

第一个问题是您尝试对函数进行两次原型设计。另一个问题是,当您在类中时,声明成员函数时不需要Complex::。选择第二个。

zakinster 的回答涵盖了其余部分。

【讨论】:

    【解决方案3】:

    首先,您的比较运算符应该比较Complex 的两个实例,可以写成:

    bool Complex::operator<(const Complex&  other) {
        return (this->it1->first) < (other.it1->first);
    }  
    

    其次,你似乎不需要那个操作员来做你想做的事。 std::map&lt;float, origin_of_tactics, CompareFloat&gt; 的元素已经使用比较器CompareFloat(或默认的operator&lt;,如果未指定)按float 键排序。

    您可以像这样遍历 always 排序的值:

    map<float, origin_of_tactics, CompareFloat> origin;
    for (iter_type it = origin.begin(); it != origin.end(); ++it)
    {
        ...
    }
    

    如果您想遍历地图索引的子集,可以使用std::map::lower_boundstd::map::upper_bound

    float beginIndex, endIndex;
    iter_type begin = origin.lower_bound(beginIndex);
    iter_type end = origin.upper_bound(endIndex);
    for (iter_type it = begin; it == end; ++it)
    {
        ...
    }
    

    【讨论】:

    • 为什么要在带有float 键的映射中查找条目?
    • @juanchopanza 我也不明白 Complex 类的用途。
    • 对,基本上问题中的代码完全没有意义。
    • 嗨 zakinster,1) 我不知道如何在同一个类中编写它,这就是我使用 Complex 类的原因。 2)关于答案: for (iter_type it = origin.begin(); it != origin.end(); ++it) 在 it == origin.end() 的情况下如何进入循环?谢谢
    • @user2162793 origin.end()不指向地图的任何元素,它指的是理论上的past the end element,如果origin.begin()==origin.end()表示你的地图是空的。所以你不想进入循环它it == origin.end()
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-11-27
    • 1970-01-01
    • 2016-02-19
    • 1970-01-01
    • 2016-04-08
    • 2012-06-02
    相关资源
    最近更新 更多