使用带有比较结构的Lower_bound将对象插入向量中

时间:2019-04-10 11:38:43

标签: c++ vector insert const lower-bound

我上了这个课:

class Mail {
  public:
    Mail(const string & msg) : msg(msg) {}

    const string msg;
};

此结构比较两个Mail对象:

struct Compare {
  bool operator()(const Mail & mail, Mail const & mail2) const {
    return mail.msg < mail2.msg;
  }
};

我想要一个包含Mail对象的向量,这些对象按其消息const string msg排序。但是,当我尝试使用lower_bound将新对象插入向量时,会遇到很多错误,包括:

  

将const字符串作为“ this”参数传递会丢弃限定符。

int main() {
  vector <Mail> mails;

  Mail mail2("1");
  mails.push_back(mail2);

  const string msg = "2";
  Mail mail(msg);
  auto low = lower_bound(mails.begin(), mails.end(), mail, Compare());

  // mails.push_back(mail);   // OK
  mails.insert(low, mail); // passing ‘const string as ‘this’ argument discards qualifiers

  return 0;
}

我对const的用法尚不甚了解,无法弄清哪个const是错误的。
很抱歉,如果已经问过这个问题,但是我还没有找到解决这个问题的答案。

2 个答案:

答案 0 :(得分:0)

由于const string msg;类中的Mail成员,这里的问题与删除的副本分配运算符和删除的移动分配运算符有关:

  

Deleted implicitly-declared copy assignment operator

     

如果满足以下任一条件,则将类别T 的默认副本分配运算符定义为已删除

     
      
  • T具有一个非类类型(或其数组)的非静态数据成员,即const;
  •   
     

Deleted implicitly-declared move assignment operator

     

对于类T 的隐式声明或默认的移动分配运算符,如果满足以下任一条件,则定义为已删除

     
      
  • T具有一个非静态数据成员const;
  •   

答案 1 :(得分:0)

C ++中的错误有时很难诊断。我的提示是始终从顶部开始并首先解决该问题。在这种情况下,有a long list of them,但它们实际上是同一回事–无法生成Mail的赋值运算符。

以这种方式考虑,编译器很有帮助,并且正在尝试生成(并在lower_bound()中使用)此函数:

Mail& operator=( const& Mail mail ) 
{ 
    msg = mail.msg; 
    return *this;
}

但这不是因为msgconst,所以主体中的赋值无效。您也不能自己真正编写它,因为您也不能分配给const变量。

通常不需要成员变量为const,因为如果类的实例本身为const,则它们变为const

const auto mail1 = Mail{"1"};
auto       mail2 = Mail{"2"};

mail1.msg = "3"; // FAIL! msg is const since mail1 is const
mail2.msg = "4"; // Ok! msg is not const

如果确实需要const成员,则不能在该类中使用赋值运算符。他们是休息。

删除const和所有作品:

#include <vector>
#include <string>
#include <algorithm>

using namespace std;

class Mail {
  public:
    Mail(const string & msg) : msg(msg) {}

    string msg; //////////////////////////////// Not const!
};

struct Compare {
  bool operator()(const Mail & mail, Mail const & mail2) const {
    return mail.msg < mail2.msg;
  }
};

int main() {
  vector <Mail> mails;

  Mail mail2("1");
  mails.push_back(mail2);

  const string msg = "2";
  Mail mail(msg);
  auto low = lower_bound(mails.begin(), mails.end(), mail, Compare());

  // mails.push_back(mail);   // OK
  mails.insert(low, mail); // OK!

  return 0;
}

看到它在 Coliru 上实时运行。

脚注

  • 您可以使用lambda来作为同伴,以免在类Compare周围出现一些重复的例子:
const auto low = lower_bound( begin(mails), end(mails), mail, 
                              []( const auto& mail1, const auto& mail2 ) 
                              { return mail1.msg < mail2.msg; } );
  • 您可以使用vector::emplace_back()来构造项目,避免复制。以下代码块实际上起到了相同的作用,但是第二个代码块效率更高:
const auto mail = Mail{"2"};
mails.push_back( mail2 ); // Copies

mails.emplace_back("2"); // Creates it right in the vector
  • 如果您知道要在向量中放入多少个项目,请考虑使用vector::reserve()