当前位置: 首页 > 知识库问答 >
问题:

为什么在成员函数上指定*this的左值引用不同于不指定任何内容?

羊舌涵涤
2023-03-14

考虑以下代码:

#include <iostream>
using namespace std;

struct A {
    void f() { cout << "A::f" << endl; }
    void f() const { cout << "A::f const" << endl; }
};

struct B {
    void f() & { cout << "B::f &" << endl; }
    void f() const & { cout << "B::f const &" << endl; }
};

A getA() { return A{}; }
B getB() { return B{}; }

int main() {
    getA().f();
    getB().f();
}

哪个打印

A::f
B::f const &

对于B,将选择常量重载,而不是非常量重载。我想这意味着为*指定左值ref限定符与根本不指定任何内容是不同的。为什么会这样?“implicit this argument”是否改变了类型,const重载现在是否成为重载解析中更好的候选者?

共有2个答案

公良俊楚
2023-03-14

作为参考,完全误导我的句子在[over.match.funcs],N3337的§13.3.1/4中:

-“对cv X的左值引用”,用于声明没有ref限定符或

-使用声明的函数的“rvalue引用cv X”

(我的重点)。

所以我有点疯狂地想知道为什么输出会有差异。没有或使用

嗯,原因是后来在§13.3.1/5中潜入了一条附加规则

对于未使用ref限定符声明的非静态成员函数,另一条规则适用:

-即使隐式对象参数不是const限定的,只要在所有其他方面参数可以转换为隐式对象参数的类型,就可以将右值绑定到参数。

这基本上触发了非常量右值到非常量左值的转换,并在上面的示例中产生了所有差异。嗯。

仲孙翔飞
2023-03-14

在这种情况下:

struct A {
    void f() { cout << "A::f" << endl; }
    void f() const { cout << "A::f const" << endl; }
};

getA().f();

这两种重载对于f都是可行的,但非常量重载是首选的,因为它不需要转换。

但在这种情况下:

struct B {
    void f() & { cout << "B::f &" << endl; }
    void f() const & { cout << "B::f const &" << endl; }
};

getB().f();

第一个重载要求this是左值。但是在getB(). f()中,getB()的结果是一个prvalue,它不能绑定到非const左值。所以这个重载是不可行的,也没有被选择。

然而,第二个重载要求this是一个const左值,prvalue可以绑定到该值:此重载是可行的,并由编译器选择。

 类似资料:
  • 我有一堂简单的课 当我尝试编译时,我收到了这条消息: 错误:将“const foo”作为“void foo::func2()”的“this”参数传递将丢弃限定符[-fpermissive] 我理解const对象的非const成员的使用,我的问题是“this”指针如何用作函数2的参数?

  • 当一个类具有 constexpr 成员函数并且该成员函数正在 constexpr 上下文中的 l 值对象上求值时,clang 和 gcc 不同意结果是否为 constexpr 值。为什么?是否有既不需要默认可构造性也不需要复制可构造性的解决方法? 当对象按值传递时,两个编译器都会成功编译。 Clang版本trunk,8,7: 和 gcc 版本主干,8.1、7.4:编译没有错误 https://go

  • 问题内容: 基本上,我已经在正常的完整查询中创建了一个数据库,这是我使用的代码以及生成的响应。 生成的查询如下: 这是合乎逻辑的,因为我正在从表中提取所有内容。但是,当我尝试使用load_only专门选择一列时,在这种情况下为email列。我使用的代码是: 这两个命令给我相同的结果: 这非常奇怪,因为我应该在查询中仅获得一列。但是,当我使用此: 它神奇地为我返回了仅一列。我需要使用load_onl

  • 这与为什么GCC不能为两个int32s的结构生成最优运算符==有关?。我在godbolt.org玩弄那个问题的代码,注意到了这个奇怪的行为。 https://godbolt.org/z/e49h6d 对于非零ptr,clang-O3(所有版本)生成此代码或类似代码: 这严格实现了C函数的短路行为,仅当x字段为零时加载y字段。 对于非零参考,clang 3.6和更早版本生成与非零ptr相同的代码,但

  • 使用Jooq,我想在作为函数插入期间指定字段的值。 在SQL Server中,等效查询为:

  • 我的mavensettings.xml如下,如你所见,没有超文本传输协议repository url,所有repository url都是以https开头的。 当我执行 gradle 构建时,它说我使用不安全的协议。事实上,我从来没有在我的专家设置中使用过http协议.xml。我们可以看到所有存储库 URL 都以“https://”开头。任何人都可以给我一些建议吗? 我的gradle版本是7.4部