方法调用意外地像 l 值一样起作用
Method call acting unexpectedly like an l-value
谁能解释为什么这段代码编译:
typedef struct longlong
{
unsigned long low;
long high;
}
longlong;
typedef longlong Foo;
struct FooStruct
{
private:
Foo bar;
public:
void SetBar(Foo m)
{
bar = m;
}
Foo GetBar()
{
return bar;
}
};
int main()
{
FooStruct f;
Foo m1 = { 1,1 };
Foo m2 = { 2,2 };
f.SetBar(m1);
f.GetBar() = m2; // Here I'd expect an error such as
// "error: lvalue required as left operand of assignment"
}
我预计编译会因在线f.GetBar() = m2;
error: lvalue required as left operand of assignment
而失败,因为 IMOf.GetBar()
不是 l 值,但它编译得无形,f.GetBar() = m2;
是 NOP。
另一方面,如果我将typedef longlong Foo;
替换为typedef long Foo;
,前面提到的行将无法编译,并且我得到预期的错误。
我在重构一些旧代码时遇到了这个问题。此问题中的代码除了说明此问题外没有任何目的。
这是有效的,因为longlong
是一个类,因此=
是隐式定义的赋值运算符longlong::operator =
。你可以调用临时成员函数,只要它们不是用&
限定的(默认operator =
是非限定的)。
若要将赋值运算符限制为左值,可以使用其他 ref 限定符显式默认它:
struct longlong
{
longlong &operator = (longlong const &) & = default;
// ^
// ...
};
在类类型的对象上使用运算符意味着调用函数(左侧操作数的成员函数,或将左侧操作数作为第一个参数的自由函数)。这称为运算符重载。
可以调用右值上的函数,这样就不会出现编译错误。
在实现重载赋值运算符时,您可以对其进行标记,以便不能在右值上调用它,但是您使用的任何类的设计者都选择不这样做。
f.GetBar() = m2; // Here I'd expect an error such as // "error: lvalue required as left operand of assignment"
你的期望是错误的。此规则仅适用于内置类型的对象。
[C++14: 3.10/5]:
为了修改对象,对象的左值是必需的,但在某些情况下,类类型的右值也可用于修改其引用。[ 示例:为对象 (9.3) 调用的成员函数可以修改该对象。—结束示例 ]
回想一下,您在此处=
实际上是对operator=
的调用,这是一个函数。
其他答案中描述了这种行为的原因。
避免此行为的一种方法是使用const
限定返回类型:
struct FooStruct
{
...
const Foo GetBar() {return bar;}
};
不能为const
对象赋值,因此编译器会抱怨。
- 我的神经网络不起作用 [XOR 问题]
- 在C++程序中输入的文本文件将不起作用,除非文本被复制和粘贴
- C++映射:具有自定义类的运算符[]不起作用(总是返回0)
- C++为什么尽管我调用了void函数,它却不起作用
- 为什么在保护模式下继承升级不起作用
- 循环在计数器中不起作用
- 在其他文件中创建类时在 c++ 项目中不起作用
- Visual studio代码重构似乎不起作用(例如,重命名符号-f2)
- 为什么二进制搜索在我的测试中不起作用
- 我的代码中有错误吗?使用BGI图形的C++代码对我不起作用
- 为什么 const std::p air<K,V>& 在 std::map 上基于范围的 for 循环不起作用?
- 带有指定长度字符* 参数的 std::regex_search 在 VS2017 中不起作用?
- Bjarne Stroustrup Book - std_lib_facilities.h - 不起作用(未知类型名称)
- 为什么简单的算术减法在"if"条件下不起作用?
- 为什么Stroustup书中的has_f不起作用
- 你能检查一下为什么在这个代码中从链接列表中删除项目不起作用吗
- 方法调用意外地像 l 值一样起作用
- 像在 Python 中一样C++循环中的参数解析。为什么不起作用?
- 输入字母f或任何字母,并像ABC ABCD ABCDE ABCDEF一样cout字母模式,但仅在我按0时起作用
- C 代码在像C++一样编码时不起作用