【问题标题】:Implicit call of constructor from operator==从 operator== 隐式调用构造函数
【发布时间】:2012-06-27 14:57:16
【问题描述】:

我有以下代码:

class Employee {
friend string FindAddr( list<Employee> lst,string name );
public:
Employee(const string& s){ cout << "Employee CTOR" << endl;}
bool operator==( Employee& e) {
    return e.name == name;
}
private:
string name;
string addr;
};


string FindAddr( list<Employee> lst, string name ) { 
string result = "";
for( list<Employee>::iterator itr = lst.begin(); itr != lst.end(); itr++ ) { 
    if ( *itr == name ) { // Problematic code
        return (*itr).addr;
    }
}
return result;
}

据我了解,有问题的行if ( *itr == name ) 应遵循以下步骤:

  1. Employee 类上识别它是operator==
  2. 试图确定是否存在从string nameEmployee 的转换,以便操作员可以工作。
  3. 在对象 string name 上隐式调用构造函数 Employee(const string&amp; s)
  4. 继续operator==

但是,这一行在编译时给我带来了麻烦:

Invalid operands to binary expression ('Employee' and 'string' (aka 'basic_string<char>'))

即使我显式调用构造函数:

if ( *itr == Employee::Employee(name) )

我得到同样的错误。

这令人困惑。我很难理解隐式构造函数调用何时起作用(以及为什么即使我显式调用构造函数代码也不起作用)。

谢谢!

【问题讨论】:

  • 这正是您应该在operator== 中使用const 引用的原因。
  • 提示:临时变量不能绑定到非常量引用。
  • 因为它没有改变状态,所以成员函数也应该是const,这样它就可以在const对象上调用。

标签: c++ operators implicit-conversion implicit


【解决方案1】:

规则是:
临时文件只能绑定到const 引用。

正如您提到的 == 工作,
name 类型为 std::string 的对象需要转换为 Employee 类型,您的类 Employee 中的转换运算符应该可以实现这一点。然而,创建的Employee 对象是一个临时对象。即一个无名对象,它的寿命不足以需要一个名称。这样一个无名临时对象不能绑定到一个非常量引用。[Ref 1 ]
所以你需要的是一个 const 引用:

bool operator==(const Employee& e)
                ^^^^^^

[参考 1]
制定规则的动机:
Bajrne 在C++ 的设计和演变的第 3.7 节中概述了这一特定规则的动机。

不过,我犯了一个严重的错误,即允许非常量引用由非左值初始化。例如:

void incr(int &rr) {r++;}    

void g()
{
    double ss = 1;
    incr(ss);    //note: double passed int expected
}

由于int&amp; 的类型不同,无法引用传递的double,因此生成了一个临时值来保存由ss 的值初始化的int。因此incr() 修改了临时的,结果没有反映回函数。

因此,很多时候临时对象是在函数调用中在不知不觉中生成的,在这些函数调用中它们是最不期望的,并且可能(错误地)假设它们的函数在传递的原始对象上工作,而函数在临时对象上运行。因此很容易编写一个假设一件事并做另一件事的代码。因此,为了避免这种容易误导的情况,我们制定了规则。

【讨论】:

  • 声明函数const 也是一个好主意。或者更好的是,将其设为允许对两个参数进行转换的非成员(即允许name == *itr*itr == name)。
  • 临时文件肯定会在内存中占用一个空间并有一个​​地址......(除了那些适合寄存器的之外的所有)。此外,为什么不能将它们绑定到非常量引用的解释是...... 误导 至少可以说。 IE。这更多的是个人意见——例如,const 引用会出现完全相同的问题,并且一些编译器具有支持这一点的扩展... security 不是语言功能的原因(安全可能是)...
  • @DavidRodríguez-dribeas 实际上,做出决定的人 (Stroustrup) 已经记录了您无法使用临时值初始化非常量引用的原因:结果太错误了易于。不是因为生命周期,而是因为当你打算修改初始化对象时,你有时会在没有意识到的情况下得到临时变量并修改它们。
  • @James:我知道(我记得在 C++ 的设计和演变 中读过那几行),我只是不喜欢人们事后诸葛亮 原因和创造城市神话 :)
  • 关于 const 引用,用现代 C++ 编写它的首选方式是Employee const&amp; e
【解决方案2】:

*itr 为您提供Employee,因此您将Employee 与字符串name 进行比较。

你需要的是if ( *itr.name == name )

这样您就可以将列表名称中的Employee 与您正在搜索的名称进行比较。

【讨论】:

  • 这可行(至少使用吸气剂),但它不能解决根本问题。 *itr == name 应该可以工作。
  • 我同意,这不是我想要的解决方案。
猜你喜欢
  • 2015-02-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-09
  • 1970-01-01
  • 2013-11-02
  • 2017-12-08
  • 1970-01-01
相关资源
最近更新 更多