Member access operators
成员接入运营商
访问其操作数的一个成员。
Operator name | Syntax | Overloadable | Prototype examples (for class T) |
---|---|---|---|
Inside class definition | Outside class definition | ||
subscript | ab | Yes | R& T::operator; |
indirection | *a | Yes | R& T::operator*( |
address-of | &a | Yes | R* T::operator&( |
member of object | a.b | No | N/A |
member of pointer | a->b | Yes | R* T::operator->( |
pointer to member of object | a.*b | No | N/A |
pointer to member of pointer | a->*b | Yes | R& T::operator->*(S b |
注意:与大多数用户定义的重载一样,返回类型应该与内置操作符提供的返回类型相匹配,以便用户定义的操作符可以与内置操作相同的方式使用。但是,在用户定义的操作符重载中,任何类型都可以用作返回类型%28,包括无效%29。一个例外是运算符->,它必须返回一个指针或另一个带有重载运算符的类->才能实际使用。
- 与大多数用户定义的重载一样,返回类型应该与内置运算符提供的返回类型相匹配,以便用户定义的运算符可以以与内置相同的方式使用。但是,在用户定义的操作符重载中,任何类型都可以用作返回类型%28,包括void29%。一个例外是operator->,它必须返回一个指针或另一个重载的类。operator->才能现实地使用。解释内建下标运算符提供对指针或列阵操作数。内建间接运算符提供对指针操作数指向的对象或函数的访问。内建地址运算符创建指向对象或函数操作数的指针。对象成员和指向对象成员的指针运算符提供对类操作数的数据成员或成员函数的访问。内建指针成员和指向指针成员的指针运算符提供对指针操作数指向的类的数据成员或成员函数的访问。内建下标运算符对于每种对象类型T%28可能是cv-限定%29,以下函数签名参与过载解析:T&算子;二次二次T&算子;二次二次非指针操作数可以是整数或非范围枚举类型的任何表达式,它是隐式转换到std::ptrdiff_t.表达E1[E2]与表达式完全相同。*(E1 + E2),即指针操作数%28(它可能是数组到指针转换的结果),并且必须指向某个数组的元素,或者指向某个数组的元素,或者在结束%29之后的一个元素,将其调整为指向同一数组的另一个元素,遵循指针算法,然后被取消引用。当应用于数组时,下标表达式为洛值如果数组是一个lvalue,并且x值如果是自C++11%29以来的%27T%28。当应用于指针时,下标表达式始终是lvalue。类型T不允许成为不完全类型的大小或内部结构T从未使用过,如&x[0]...二次#include <iostream> int main() { int a[4] = {1, 2, 3, 4}; int* p = &a[2]; std::cout << p[1] << p[-1] << 1[p] << (-1)[p] << '\n'; }二次产出:二次4242二次内建间接算子每种类型T即对象类型%28可能是cv限定%29,或者函数类型%28不是Const-或ref-限定%29,下列函数签名参与重载解析:T&算子%2A%28吨%2A29%;二次二次内置间接操作符的操作数是指向对象或函数的指针,结果是指针所指向的lvalue。指向%28的指针CV-合格%29void不能取消引用。指向其他不完全类型的指针可以取消引用,但是得到的lvalue只能在允许不完全类型的lvalue的上下文中使用,例如在初始化引用时。二次#include <iostream> int f() { return 42; } int main() { int n = 1; int* pn = &n; int& r = *pn; // lvalue can be bound to a reference int m = *pn; // indirection + lvalue-to-rvalue conversion int (*fp)() = &f; int (&fr)() = *fp; // function lvalue can be bound to a reference }二次内建地址内建的操作数。operator&是任何类型的lvalue表达式,或者是某个类中非静态数据成员或成员函数的限定名。此操作员不参与过载解析。如果没有可行函数,采用特别规则:
- 如果操作数是某种类型的lvalue表达式
T
,,,operator&
创建并返回类型的prvalue。T*
,具有相同的cv限定条件,即指向操作数指定的对象。如果操作数具有不完全类型,则可以形成指针,但如果该不完全类型恰好是定义自己的类。operator&
,在C++14%29之前,该行为是未定义的%28,因为C++14%29中未指定内置还是重载使用%28。用于具有用户定义的类型操作数。operator&
,,,std::addressof
可用于获取真正的指针。
- 如果操作数是重载函数的名称,则只有在由于上下文原因可以解决重载时,才能使用该地址。见重载函数的地址关于细节。
- 如果操作数是一个非静态成员的限定名,例如,
&C::member
,则结果是一个prvalue。指向成员函数的指针或指向数据成员的指针类型T
上课时C
请注意,两者&member
也不C::member
甚至连&(C::member)
可用于初始化指向成员的指针。
二次
void f(int) {}
void f(double) {}
struct A { int i; };
struct B { void f( };
int main()
{
int n = 1;
int* pn = &n; // pointer
int* pn2 = &*pn; // pn2 == pn
int A::* mp = &A::i; // pointer to data member
void (B::*mpf)() = &B::f; // pointer to member function
void (*pf)(int) = &f; // overload resolution due to initialization context
// auto pf2 = &f; // error: ambiguous overloaded function type
auto pf2 = static_cast<void (*)(int)>(&f // overload resolution due to cast
}
二次
内置成员接入运营商
的第一个操作数。operator.是表示完全类类型T.内置的第一个操作数。operator->是指向完整类类型的指针的表达式。T*两个运算符的第一个操作数即使不是必需的%28例如。当第二个操作数指定静态成员%29时。
这两个运算符的第二个操作数是%28形式的名称,ID-表达式的数据成员或成员函数命名为%29。T或者是明确和可访问的基类。B成T%28等E1.E2或E1->E2%29,可选合资格%28等E1.B::E2或E1->B::E2%29,可选地使用模板消歧器%28等E1.template E2或E1->template E229%。
如果用户定义了operator->提供,则operator->对它返回的值再次调用,直到operator->返回普通指针的。在此之后,内置语义将应用于该指针。
表达E1->E2完全等同于(*E1).E2对于内置类型,这就是为什么以下规则仅针对E1.E2...
在表达中E1.E2
*
1%29E2
是静态数据成员*
- 如果
E2
参考型T&
或T&&
,则结果是类型的lvalue。T
指定对象或函数E2
指的是,
- 否则,结果是一个指定静态数据成员的lvalue。
基本上,E1
在这两种情况下都会被评估和丢弃;2%29E2
是非静态数据成员*
- 如果
E2
参考型T&
或T&&
,则结果是类型的lvalue。T
指定对象或函数E2
指的是,
- 否则,如果
E1
的值,则结果是表示非静态数据成员的lvalue。E1
,,,
- 否则,%28
E1
是一个rvalue%28,直到C++17%29xvalue%28,这可能是物化从自C++17%29%29以来的prvalue%29%28,结果为rvalue%28,直到C++11%29xvalue%28,因为C++11%29指定了E1
...
如果E2
不是可变成员,则简历-资格的结果是cv-资格的结合E1
和E2
,否则为%28E2
是一个可变成员%29,它是不稳定的资格的联盟。E1
和E2
;
3%29E2
是静态成员函数,结果是一个表示静态成员函数的值。基本上,E1
在这种情况下被评估和丢弃;
4%29E2
是非静态成员函数包括破坏者,结果是一种特殊的表示非静态成员函数的值。E1
它只能用作成员函数调用操作符的左操作数,而不用于其他目的;
5%29E2
是成员枚举数,则结果是与E1
;
6%29E2
是嵌套型,程序格式错误%28元%27T编译%29;
7%29E1
是标量型和E2
是~
后面跟着类型名称或解密说明符指定相同类型的%28减去cv-资格%29,可选合资格,结果是一种特殊的prvalue,只能用作函数调用操作符的左操作数,而不能用于其他目的。生成的函数调用表达式被调用伪析构调用
.它不需要参数,返回无效,并且不执行除初始计算以外的任何操作。E1
...这是唯一一种情况,在这种情况下,左操作数的operator.
有非类类型。允许伪析构函数调用可以编写代码,而不必知道某个类型是否存在析构函数。
二次
#include <iostream>
struct P
{
template<typename T>
static T* ptr() { return new T; }
};
template<typename T>
struct A
{
A(int n): n(n) {}
int n;
static int sn;
int f() { return 10 + n; }
static int sf() { return 4; }
class B {};
enum E {RED = 1, BLUE = 2};
void g()
{
typedef int U;
// keyword template needed for a dependent template member
int* p = T().template ptr<U>(
p->~U( // U is int, calls int's pseudo destructor
delete p;
}
};
template<> int A<P>::sn = 2;
int main()
{
A<P> a(1
std::cout << a.n << ' '
<< a.sn << ' ' // A::sn also works
<< a.f() << ' '
<< a.sf() << ' ' // A::sf() also works
// << a.B << ' ' // error: nested type not allowed
<< a.RED << ' '; // enumerator
}
二次
产出:
二次
1 2 11 4 1
二次
内置指针到成员访问操作符
的第一个操作数。operator.*是类类型的表达式。T的第一个操作数operator->*是指向类类型的类型指针的表达式。T*...
两个运算符的第二个操作数是指向T
或指向明确和可访问基类的成员的指针。B
成T
...
对于每一种类型组合D
,,,B
,,,R
,其中的类类型B
是与D
的一个明确和可访问的基类D
,和R
是对象或函数类型,以下函数签名参与重载解析:
R& operator->*(D*, R B::* | | |
---|
如果两个操作数都可以是cv限定的,则返回类型%27s cv限定是操作数的cv限定的结合。
表达E1->*E2完全等同于(*E1).*E2对于内置类型,这就是为什么以下规则仅针对E1.*E2...
在表达中E1.*E2
*
1%29E2
是指向数据成员的指针,
- 如果
E1
是一个lvalue,结果是一个指定数据成员的lvalue,
- 否则,%28
E1
是一个rvalue%28,直到C++17%29xvalue%28,这可能是从自C++17%29%29以来,结果为rvalue%28,直到C++11%29xvalue%28自C++11%29指定该数据成员为止;
2%29E2
是指向成员函数的指针,其结果是一种特殊的值,表示该成员函数只能用作成员函数调用操作符的左操作数,而不用于其他目的;
3%29 cv-限定规则与对象操作符的成员相同,但有一个附加规则:指向引用可变成员的成员的指针不能用于修改Const对象中的成员;
4%29E2
为空指针到成员值,行为未定义;
5%29如果动态类型成E1
不包含E2
指的是,行为是不明确的;
6%29E1
是一个rvalue和E2
指向带有ref-限定符的成员函数&程序格式不正确;
7%29E1
是一个独立的E2
指向带有ref-限定符的成员函数&&,程序的格式不正确。
二次
#include <iostream>
struct S
{
S(int n): mi(n) {}
mutable int mi;
int f(int n) { return mi + n; }
};
struct D: public S
{
D(int n): S(n) {}
};
int main()
{
int S::* pmi = &S::mi;
int (S::* pf)(int) = &S::f;
const S s(7
// s.*pmi = 10; // error: cannot modify through mutable
std::cout << s.*pmi << '\n';
D d(7 // base pointers work with derived object
D* pd = &d;
std::cout << (d.*pf)(7) << ' '
<< (pd->*pf)(8) << '\n';
}
二次
产出:
二次
7
14 15
二次
标准库
下标运算符被许多标准容器类重载。
operator[] | accesses specific bit (public member function of std::bitset) |
---|---|
operator[] | provides indexed access to the managed array (public member function of std::unique_ptr) |
operator[] | access specified character (public member function of std::basic_string) |
operator[] | access specified element (public member function of std::array) |
operator[] | access specified element (public member function of std::deque) |
operator[] | access specified element (public member function of std::vector) |
operator[] | access specified element (public member function of std::map) |
operator[] | access specified element (public member function of std::unordered_map) |
operator[] | accesses an element by index (public member function of std::reverse_iterator) |
operator[] | accesses an element by index (public member function of std::move_iterator) |
operator[] | get/set valarray element, slice, or mask (public member function of std::valarray) |
operator[] | returns specified sub-match (public member function of std::match_results) |
间接和成员运算符被许多迭代器和智能指针类重载。
operator*operator-> | dereferences pointer to the managed object (public member function of std::unique_ptr) |
---|---|
operator*operator-> | dereferences the stored pointer (public member function of std::shared_ptr) |
operator*operator-> | accesses the managed object (public member function of std::auto_ptr) |
operator* | dereferences the iterator (public member function of std::raw_storage_iterator) |
operator*operator-> | dereferences the decremented underlying iterator (public member function of std::reverse_iterator) |
operator* | no-op (public member function of std::back_insert_iterator) |
operator* | no-op (public member function of std::front_insert_iterator) |
operator* | no-op (public member function of std::insert_iterator) |
operator*operator-> | accesses the pointed-to element (public member function of std::move_iterator) |
operator*operator-> | returns the current element (public member function of std::istream_iterator) |
operator* | no-op (public member function of std::ostream_iterator) |
operator*operator-> (since C++11)(until C++17) | obtains a copy of the current characteraccesses a member of the current character, if CharT has members (public member function of std::istreambuf_iterator) |
operator* | no-op (public member function of std::ostreambuf_iterator) |
operator*operator-> | accesses the current match (public member function of std::regex_iterator) |
operator*operator-> | accesses current submatch (public member function of std::regex_token_iterator) |
没有标准库类重载operator&
.最著名的超载例子operator&
是microsoft com类。CComPtr%28http://msdn.microsoft.com/en-us/Library/31k6d0k7%28V=vs.100%29.aspx%29,尽管它也可以出现在诸如酒鬼...
没有标准库类重载operator->*.有人建议它可能是智能指针接口,而事实上,行为者以这种身份使用加油。凤凰城,但是在edsl中更常见,例如cpp.反应...
缺陷报告
以下行为更改缺陷报告追溯应用于先前发布的C++标准。
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
CWG 1213 | C++11 | subscripting an array rvalue resulted in lvalue | reclassified as xvalue |
另见
运算符优先...
操作者超载...
公共算子
*。
分配增量递减算术逻辑比较成员访问其他
a=b a+=b a-=b a%2A=b a/=b a%=b a&=b a=b a^=b a<=b a>>=b.+a-a+a-+a-+a-a+b a-b a%2Ab a/b a%b~a&b ab^b a<<b a>>b.%21 a&b a&b ab a=b a%21=b a<b a>b a<=b a>=b a乙%2AA&A->b A.B a->%2Ab a.%2AA%28...%29 a,b?*
特殊运算符
静态[医]强制转换将一种类型转换为另一种相关类型动态。[医]继承层次结构中的强制转换[医]强制转换添加或删除cv限定符,重新解释[医]CAST将类型转换为不相关的类型C风格的强制转换通过混合静态方式将一种类型转换为另一种类型[医]卡斯特[医]重释[医]强制转换新创建具有动态存储持续时间的对象,删除删除以前由新表达式创建的对象,并释放获得的内存区域大小查询类型的大小...查询参数Pack%28的大小,因为C++11%29 Tyid查询类型no的类型信息,除了检查。表达式可以抛出异常%28,因为C++11%29查询对齐要求类型为%28,因为C++11%29。
© cppreference.com
在CreativeCommonsAttribution下授权-ShareAlike未移植许可v3.0。
http://en.cppreference.com/w/cpp/language/Operator[医]成员[医]存取