gpt4 book ai didi

c++ - 成员函数签名末尾的&(符号)是什么意思?

转载 作者:可可西里 更新时间:2023-11-01 18:26:10 32 4
gpt4 key购买 nike

我不记得是哪次演讲了,但最近我看了 CppCon 2017 的一些演讲,有人在旁注中提到,唯一正确重载 operator= 将采用以下方式:

class test {
public:
test& operator=(const test&) &;
};

他明确强调了尾随的 & 但没有说明它的作用。

那么它有什么作用呢?

最佳答案

引用限定符 - 在 C++11 中引入

Ref-qualifiers 不是 C++17 特性(查看问题的标签),而是 C++11 中引入的特性。

struct Foo
{
void bar() const & { std::cout << "const lvalue Foo\n"; }
void bar() & { std::cout << "lvalue Foo\n"; }
void bar() const && { std::cout << "const rvalue Foo\n"; }
void bar() && { std::cout << "rvalue Foo\n"; }
};

const Foo&& getFoo() { return std::move(Foo()); }

int main()
{
const Foo c_foo;
Foo foo;

c_foo.bar(); // const lvalue Foo
foo.bar(); // lvalue Foo
getFoo().bar(); // [prvalue] const rvalue Foo
Foo().bar(); // [prvalue] rvalue Foo

// xvalues bind to rvalue references, and overload resolution
// favours selecting the rvalue ref-qualifier overloads.
std::move(c_foo).bar(); // [xvalue] const rvalue Foo
std::move(foo).bar(); // [xvalue] rvalue Foo
}

请注意,右值可用于初始化 const 左值引用(并以此扩展右值标识的对象的生命周期),这意味着如果我们从上面的示例中删除右值引用限定符重载,则示例中的右值值类别将全部支持剩余的 const & 重载:

struct Foo
{
void bar() const & { std::cout << "const lvalue Foo\n"; }
void bar() & { std::cout << "lvalue Foo\n"; }
};

const Foo&& getFoo() { return std::move(Foo()); }

int main()
{
const Foo c_foo;
Foo foo;

// For all rvalue value categories overload resolution
// now selects the 'const &' overload, as an rvalue may
// be used to initialize a const lvalue reference.
c_foo.bar(); // const lvalue Foo
foo.bar(); // lvalue Foo
getFoo().bar(); // const lvalue Foo
Foo().bar(); // const lvalue Foo
std::move(c_foo).bar(); // const lvalue Foo
std::move(foo).bar(); // const lvalue Foo
}

参见例如以下博文作简要介绍:


右值不能调用非const & 重载

为了可能解释你从 CppCon 谈话中记忆起的引述的意图,

"... that the only true way of overloading operator= ..."

我们访问[over.match.funcs]/1, /4 & /5 [强调我的]:

/1 The subclauses of [over.match.funcs] describe the set of candidate functions and the argument list submitted to overload resolution in each context in which overload resolution is used. ...

/4 For non-static member functions, the type of the implicit object parameter is

  • (4.1) — “lvalue reference to cv X” for functions declared without a ref-qualifier or with the & ref-qualifier

  • (4.2) — “rvalue reference to cv X” for functions declared with the && ref-qualifier

where X is the class of which the function is a member and cv is the cv-qualification on the member function declaration. ...

/5 ... For non-static member functions declared without a ref-qualifier, an additional rule applies:

  • (5.1) — even if the implicit object parameter is not const-qualified, an rvalue can be bound to the parameter as long as in all other respects the argument can be converted to the type of the implicit object parameter. [ Note: The fact that such an argument is an rvalue does not affect the ranking of implicit conversion sequences. — end note ]

从上面的/5 开始,以下重载(显式 & 引用限定符已被省略)

struct test
{
test& operator=(const test&) { return *this }
}

允许将值分配给右值,例如

int main()
{
test t1;
t1 = test(); // assign to l-value
test() = t1; // assign to r-value
}

但是,如果我们使用 & 引用限定符显式声明重载,[over.match.funcs]/5.1不适用,只要我们不提供用 && ref-qualifier 声明的重载,就不允许右值赋值。

struct test
{
test& operator=(const test&) & { return *this; }
};

int main()
{
test t1;
t1 = test(); // assign to l-value
test() = t1; // error [clang]: error: no viable overloaded '='
}

对于在声明自定义赋值运算符重载时是否显式包含 & 引用限定符“唯一正确的重载方式operator=<,我不会发表任何意见,但我敢推测,那么我猜这样的声明背后的意图是排除 to-r 值赋值。

作为一个正确设计的赋值运算符,可以说永远不应该是 const(const T& operator=(const T&) const & 没有多大意义),并且作为右值不能用于初始化非常量 左值引用,operator= 的一组重载对于给定类型 T 仅包含 T& operator=(const T&) & 永远不会提供可以从标识为右值类别的 T 对象调用的可行重载。

关于c++ - 成员函数签名末尾的&(符号)是什么意思?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47002799/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com