首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Pointer declaration

声明指针或指针到成员类型的变量。

句法

指针声明是指其报关员有表格。

* attr(optional) cv(optional) declarator

(1)

?

nested-name-specifier * attr(optional) cv(optional) declarator

(2)

?

1%29指针声明符*宣言S* D;宣告D作为由decl-说明符-seq确定的类型的指针。S...

2%29指向成员声明器的指针*宣言S C::* D;宣告D的非静态成员的指针。C由decl-说明符-seq确定的类型S...

declarator

-

any declarator other than a reference declarator (there are no pointers to references). It can be another pointer declarator (pointer to pointers are allowed)

attr(C++11)

-

optional list of attributes

cv

-

const/volatile qualification which apply to the pointer that is being declared (not to the pointed-to type, whose qualifications are part of decl-specifier-seq)

nested-name-specifier

-

a sequence of names and scope resolution operators ::

没有指向参考文献也没有指向位字段...

指向对象的指针

对象的返回值初始化指向对象的指针。地址-of接线员应用于对象类型的任何表达式,包括另一种指针类型:

二次

代码语言:javascript
复制
int n;
int* np = &n; // pointer to int
int* const* npp = &np; // non-const pointer to const pointer to non-const int
 
int a[2];
int (*ap)[2] = &a; // pointer to array of int
 
struct S { int n; };
S s = {1};
int* sp = &s.n; // pointer to the int that is a member of s

二次

指针可以显示为内建的间接运算符%28的操作数。operator*%29,它返回lvalue表达式识别指向对象:

二次

代码语言:javascript
复制
int n;
int* p = &n;     // pointer to n
int& r = *p;     // reference is bound to the lvalue expression that identifies n
r = 7;           // stores the int 7 in n
std::cout << *p; // lvalue-to-rvalue implicit conversion reads the value from n

二次

指向类对象的指针也可能显示为成员访问操作符的左侧操作数。操作员->和操作员->%2A...

因为数组对指针隐式转换,指向数组的第一个元素的指针可以用数组类型的表达式初始化:

二次

代码语言:javascript
复制
int a[2];
int* p1 = a; // pointer to the first element a[0] (an int) of the array a
 
int b[6][3][8];
int (*p2)[3][8] = b; // pointer to the first element b[0] of the array b,
                     // which is an array of 3 arrays of 8 ints

二次

因为导出基指针的隐式转换,指向基类的指针可以用派生类的地址初始化:

二次

代码语言:javascript
复制
struct Base {};
struct Derived : Base {};
 
Derived d;
Base* p = &d;

二次

如果Derived是多态,这样的指针可以用来创建虚函数调用...

定加减,,,增量和递减运算符是为数组元素的指针定义的:这些指针满足RandomAccessIterator要求和允许C++库算法若要处理原始数组,请执行以下操作。

比较算子在某些情况下,为指向对象的指针定义:两个表示相同地址的指针比较相等,两个空指针值比较相等,指向同一数组的元素的指针与这些元素的数组索引比较相同,指向非静态数据成员的指针具有相同的指针。成员访问按照这些成员的声明顺序进行比较。

许多实现还提供了严格全序的指针,例如,如果它们是在连续虚拟地址空间中作为地址实现的。那些没有%28例如的实现。如果指针的并非所有位位都是内存地址的一部分,因此必须忽略以进行比较,或者需要额外的计算,否则指针和整数不是1到1的关系%29,则提供一个专门化的std::less有这个保证的指针。这样就可以在标准关联容器中使用所有随机来源的指针作为键,例如std::setstd::map...

指向函数的指针

指向函数的指针可以用非成员函数或静态成员函数的地址初始化。因为函数对指针隐式转换时,Address-of运算符是可选的:

二次

代码语言:javascript
复制
void f(int);
void (*p1)(int) = &f;
void (*p2)(int) = f; // same as &f

二次

与函数或对函数的引用不同,指向函数的指针是对象,因此可以存储在数组中、复制、分配等等。

函数的指针可用作函数调用算子,这将调用指向函数:

二次

代码语言:javascript
复制
int f(int n)
{
    std::cout << n << '\n';
    return n * n;
}
 
int main()
{
    int (*p)(int) = f;
    int x = p(7);
}

二次

删除函数指针将产生标识指向函数的lvalue:

二次

代码语言:javascript
复制
int f();
int (*p)() = f;  // pointer p is pointing to f
int (&r)() = *p; // the lvalue that identifies f is bound to a reference
r();             // function f invoked through lvalue reference
(*p)();          // function f invoked through the function lvalue
p();             // function f invoked directly through the pointer

二次

如果只有一个重载匹配指针%28的类型,则可以从重载集初始化指向函数的指针,该重载集可以包括函数、函数模板专门化和函数模板。重载函数的地址关于更多细节,%29:

二次

代码语言:javascript
复制
template<typename T> T f(T n) { return n; }
double f(double n) { return n; }
 
int main()
{
    int (*p)(int) = f; // instantiates and selects f<int>
}

二次

相等比较算子为指向函数%28的指针定义,如果指向相同的函数%29,则它们比较相等。

指向数据成员的指针

指向非静态成员对象的指针。m是班级的一员C可以用表达式初始化。&C::m没错。表达式,如&(C::m)&m在C%27s成员函数中,不形成指向成员的指针。

该指针可用作指针到成员访问操作符operator.*operator->**

二次

代码语言:javascript
复制
struct C { int m; };
 
int main()
{
    int C::* p = &C::m;          // pointer to data member m of class C
    C c = {7};
    std::cout << c.*p << '\n';   // prints 7
    C* cp = &c;
    cp->m = 10;
    std::cout << cp->*p << '\n'; // prints 10
}

二次

指向可访问的无歧义非虚拟基类的数据成员的指针可以是隐式转换指向派生类的相同数据成员的指针:

二次

代码语言:javascript
复制
struct Base { int m; };
struct Derived : Base {};
 
int main()
{
    int Base::* bp = &Base::m;
    int Derived::* dp = bp;
    Derived d;
    d.m = 1;
    std::cout << d.*dp << ' ' << d.*bp << '\n'; // prints 1 1
}

二次

从指向派生类的数据成员的指针到指向明确的非虚拟基类的数据成员的指针,允许在相反的方向上进行转换。静态[医]铸造和显式铸造,即使基类没有该成员%28,但派生最多的类有,当指针用于访问%29时:

二次

代码语言:javascript
复制
struct Base {};
struct Derived : Base { int m; };
 
int main()
{
    int Derived::* dp = &Derived::m;
    int Base::* bp = static_cast<int Base::*>(dp);
 
    Derived d;
    d.m = 7;
    std::cout << d.*bp << '\n'; // okay: prints 7
 
    Base b;
    std::cout << b.*bp << '\n'; // undefined behavior
}

二次

指针到成员的指向类型可以是指针到成员本身:指向成员的指针可以是多级的,并且可以在每个级别上以不同的cv定性。还允许指针和指向成员的指针的混合多级组合:

二次

代码语言:javascript
复制
struct A
{
    int m;
    // const pointer to non-const member
    int A::* const p;
};
 
int main()
{
    // non-const pointer to data member which is a const pointer to non-const member
    int A::* const A::* p1 = &A::p;
 
    const A a = {1, &A::m};
    std::cout << a.*(a.*p1) << '\n'; // prints 1
 
    // regular non-const pointer to a const pointer-to-member
    int A::* const* p2 = &a.p;
    std::cout << a.**p2 << '\n'; // prints 1
}

二次

指向成员函数的指针

指向非静态成员函数的指针。f是班级的一员C可以用表达式初始化。&C::f没错。表达式,如&(C::f)&f在C%27s成员函数中,不形成指向成员函数的指针。

该指针可用作指针到成员访问操作符operator.*operator->*...结果表达式只能用作函数调用操作符的左操作数:

二次

代码语言:javascript
复制
struct C
{
    void f(int n) { std::cout << n << '\n'; }
};
 
int main()
{
    void (C::* p)(int) = &C::f; // pointer to member function f of class C
    C c;
    (c.*p)(1);                  // prints 1
    C* cp = &c;
    (cp->*p)(2);                // prints 2
}

二次

指向基类的成员函数的指针可以是隐式转换指向派生类的相同成员函数的指针:

二次

代码语言:javascript
复制
struct Base
{
    void f(int n) { std::cout << n << '\n'; }
};
struct Derived : Base {};
 
int main()
{
    void (Base::* bp)(int) = &Base::f;
    void (Derived::* dp)(int) = bp;
    Derived d;
    (d.*dp)(1);
    (d.*bp)(2);
}

二次

从指针到派生类的成员函数到指向明确的非虚拟基类的成员函数的相反方向的转换。静态[医]铸造和显式铸造,即使基类没有该成员函数%28,但派生最多的类有,当指针用于访问%29时:

二次

代码语言:javascript
复制
struct Base {};
struct Derived : Base
{
    void f(int n) { std::cout << n << '\n'; }
};
 
int main()
{
    void (Derived::* dp)(int) = &Derived::f;
    void (Base::* bp)(int) = static_cast<void (Base::*)(int)>(dp);
 
    Derived d;
    (d.*bp)(1); // okay: prints 1
 
    Base b;
    (b.*bp)(2); // undefined behavior
}

二次

指向成员函数的指针可以用作回调或函数对象,通常在应用之后。std::mem_fnstd::bind*

二次

代码语言:javascript
复制
#include <iostream>
#include <string>
#include <algorithm>
#include <functional>
 
int main()
{
    std::vector<std::string> v = {"a", "ab", "abc"};
    std::vector<std::size_t> l;
    transform(v.begin(), v.end(), std::back_inserter(l),
              std::mem_fn(&std::string::size));
    for(std::size_t n : l)
        std::cout << n << ' ';
}

二次

产出:

二次

代码语言:javascript
复制
1 2 3

二次

指向空的指针

指向任何类型的对象的指针可以是隐式转换指向指向void%28可选简历-合格29%。反向转换,它需要静态[医]铸造或显式铸造,生成原始指针值:

二次

代码语言:javascript
复制
int n = 1;
int* p1 = &n;
void* pv = p1;
int* p2 = static_cast<int*>(pv);
std::cout << *p2 << '\n'; // prints 1

二次

如果原始指针指向某种多态类型的对象中的基类子对象,动态[医]铸造可用于获取void*它指向派生类型最多的完整对象。

指向void的指针用于传递未知类型的对象,这在C接口中很常见:std::malloc回报void*,,,std::qsort期望一个用户提供的回调,它接受两个const void*争论。螺纹[医]创造期望用户提供的回调,接受并返回。void*在所有情况下,调用方%27都有责任在使用之前将指针转换为正确的类型。

空指针

每种类型的指针都有一个特殊的值,称为空指针值那种类型的。值为NULL的指针不指向对象或函数%28取消引用空指针是未定义的行为%29,并且与值也是相同类型的所有指针相比较。...

若要将指针初始化为NULL或将空值分配给现有指针,则为NULL指针文本。nullptr,空指针常量。NULL,或隐式转换从整数值?0?可能会被使用。

零-和值初始化还初始化指向其空值的指针。

空指针可用于指示缺少对象%28(例如)。function::target()%29,或作为其他错误条件指示符%28例如。动态[医]铸造29%。通常,接收指针参数的函数几乎总是需要检查值是否为NULL,并以不同的方式处理这种情况--例如,删除表达式如果传递空指针为%29,则不执行任何操作。

刚毅

  • 如果cv出现在前面*在指针声明中,它是decl-说明符-seq的一部分,并应用于指向对象。
  • 如果cv出现在*在指针声明中,它是声明器的一部分,并应用于声明%27的指针。

Syntax

meaning

const T*

pointer to constant object

T const*

pointer to constant object

T* const

constant pointer to object

const T* const

constant pointer to constant object

二次

代码语言:javascript
复制
// pc is a non-const pointer to const int
// cpc is a const pointer to const int
// ppc is a non-const pointer to non-const pointer to const int
const int ci = 10, *pc = &ci, *const cpc = pc, **ppc;
// p is a non-const pointer to non-const int
// cp is a const pointer to non-const int
int i, *p, *const cp = &i;
 
i = ci;    // okay: value of const int copied into non-const int
*cp = ci;  // okay: non-const int (pointed-to by const pointer) can be changed
pc++;      // okay: non-const pointer (to const int) can be changed
pc = cpc;  // okay: non-const pointer (to const int) can be changed
pc = p;    // okay: non-const pointer (to const int) can be changed
ppc = &pc; // okay: address of pointer to const int is pointer to pointer to const int
 
ci = 1;    // error: const int cannot be changed
ci++;      // error: const int cannot be changed
*pc = 2;   // error: pointed-to const int cannot be changed
cp = &ci;  // error: const pointer (to non-const int) cannot be changed
cpc++;     // error: const pointer (to const int) cannot be changed
p = pc;    // error: pointer to non-const int cannot point to const int
ppc = &p;  // error: pointer to pointer to const int cannot point to
           // pointer to non-const int

二次

通常,从一个多层次指针到另一个级别指针的隐式转换遵循资格转换和在指针比较算子...

代码语言:txt
复制
 ? cppreference.com

在CreativeCommonsAttribution下授权-ShareAlike未移植许可v3.0。

扫码关注腾讯云开发者

领取腾讯云代金券

http://www.vxiaotou.com