试图理解“指向成员的指针” [英] Trying to understand "pointer to member"

查看:107
本文介绍了试图理解“指向成员的指针”的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



下面是一个示例类:

$

b
$ b

  class T 
{
public:
int a;
int b [10];
void fun(){}
};

以下代码说明问题并包含问题:

  void fun(){}; 

void main()
{
T obj;
int local;
int arr [10];
int arrArr [10] [10];

int * p =& local; //standardpointer
int T :: * p =& T :: a; //指向成员的指针+T ::,即清除

void(* pF)()= fun; //这里也一切都清除
void(T :: * pF)()= T :: fun;
//或
void(T :: * pF)()=& T :: fun;

int * pA = arr; // ok
int T :: * pA = T :: b; // error

int(T :: * pA)[10] = T :: b; // error
int(T :: * pA)[10] =& T :: b; //作品;

// 1。为什么&是T :: b所需要的?对于标准指针,数组名称是数组的第一个元素的
//地址的表示。

// 2。为什么&不需要指向成员函数的指针?对于标准指针,函数名
//是函数地址的表示形式,因此在分配给指针时,我们可以写& funName或只是funName。
//这是规则在那里工作。

// 3。为什么上面的指针声明看起来像下面的指针声明:

int(* pAA)[10] = arrArr; //这里的指针设置为数组数组而不是数组。
system(pause);
}


解决方案

我认为最简单的

  int local; 
int array [10];

int * p =& local; //standardpointer to int

有人倾向于说 与指向数组的指针相同。但是 arr & arr 之间有一个重要的区别。前者不衰减到后者

  int(* p_array_standard)[10] =& arr; 

如果您& arr 得到一个指向10-int数组的指针。这不同于指向9-int数组的指针。它不同于指针到int。 sizeof(* p_array_standard)== 10 * sizeof(int)



元素,即指向 int sizeof(* p)== sizeof(int))的指针,您可以:

  int * p_standard =&(arr [0); 

到目前为止,一切都基于标准/显式指针。



在C中有一个特殊规则,它允许你用 arr &(arr [0]) $ c>。您可以使用&(arr [0])或使用 arr初始化 int * 。但是如果你真的想要一个指针数组,你必须做 int(* p_array_standard)[10] =& arr;



我认为衰变几乎可以被解释为一段语法糖。衰减不会改变任何现有代码的含义。

  int * p = arr; //给数组赋值一个指针。为什么要这样工作? 
//它的工作,但只是因为一个特殊的分配。

当数组衰减时,它衰减为指向单个元素的指针 int [10] - > int * 。它不会衰减到指向数组的指针,它将 int(* p)[10]






现在,我们可以从您的问题中查看此行:

  int T :: * pA3)[10] = T :: b; //错误

同样,类成员与理解为什么失败不相关。左边的类型是一个指针到数组的int,而不是一个指针到int。因此,正如我们前面所说的,衰减是不相关的,你需要& 来获得指向数组的int类型。



更好的问题是问为什么这不起作用(更新:我现在看到你在你的问题中有这个。

  int T :: * pA3 = T :: b; 

右侧看起来像数组,左侧是指向单个元素的指针 int * ,因此您可以合理地问:为什么不在这里衰减工作?



在这里,我们撤销语法糖,并用&(T :: b [0])替换 T :: b / code>。

  int T :: * pA3 =&(T :: b [0]); 

我认为这是你感兴趣的问题。重点关注真正的问题。此行与非成员对象一起使用,为什么它不与成员对象一起工作?



简单的回答是标准不需要它。指针衰减是一种语法糖,他们根本没有指定它必须在这样的情况下工作。



指针到成员基本上是一个比其他指针更加繁琐。它们必须直接指向在对象中出现的raw实体。
对不起,我的意思是它应该引用(间接)通过编码类的开始和这个成员的位置之间的偏移量,但我不是很好解释这个。 )
它们不能指向子对象,例如数组的第一个元素,或者数组的第二个元素。



问:现在我有一个我自己的问题。指针衰减是否可以扩展到像这样的成员数组?我认为这是有道理的。我不是唯一的想法!有关详情,请参见此讨论。这是可能的,我想没有什么阻止编译器实现它作为一个扩展。子对象,包括数组成员,与类的开头有固定的偏移,因此这是很合乎逻辑的。


I'm trying to understand how "pointer to member" works but not everything is clear for me.

Here is an example class:

class T
{
public:
    int a;
    int b[10]; 
    void fun(){}
};

The following code ilustrate the problem and contains questions:

void fun(){};

void main()
{
   T obj;                
   int local;
   int arr[10];
   int arrArr[10][10];

   int *p = &local;   // "standard" pointer
   int T::*p = &T::a; // "pointer to member" + "T::" , that is clear

   void (*pF)() = fun;        //here also everything is clear
   void (T::*pF)() = T::fun;  
   //or
   void (T::*pF)() = &T::fun;  

   int *pA = arr; // ok
   int T::*pA = T::b; // error

   int (T::*pA)[10] = T::b; // error
   int (T::*pA)[10] = &T::b; //works;

//1. Why "&" is needed for "T::b" ? For "standard" pointer an array name is the representation of the 
//   address of the first element of the array. 

//2. Why "&" is not needed for the pointer to member function ? For "standard" pointer a function name 
//   is the representation of the function address, so we can write &funName or just funName when assigning to the pointer. 
//   That's rule works there.

//3. Why the above pointer declaration looks like the following pointer declaration ?: 

   int (*pAA)[10] = arrArr; // Here a pointer is set to the array of arrays not to the array. 
   system("pause");
}

解决方案

I think the simplest thing is to forget about the class members for a moment, and recap pointers and decay.

int local;
int array[10];

int *p = &local; // "standard" pointer to int

There is a tendency for people to say that a "decayed pointer" is the same as a pointer to the array. But there is an important difference between arr and &arr. The former does not decay into the latter

int (*p_array_standard)[10] = &arr;

If you do &arr, you get a pointer to an array-of-10-ints. This is different from a pointer to an array-of-9-ints. And it's different from a pointer-to-int. sizeof(*p_array_standard) == 10 * sizeof(int).

If you want a pointer to the first element, i.e. a pointer to an int, with sizeof(*p) == sizeof(int)), then you can do:

int *p_standard = &(arr[0);

Everything so far is based on standard/explicit pointers.

There is a special rule in C which allows you to replace &(arr[0]) with arr. You can initialize an int* with &(arr[0]) or with arr. But if you actually want a pointer-to-array, you must do int (*p_array_standard)[10] = &arr;

I think the decaying could almost be dismissed as a piece of syntactic sugar. The decaying doesn't change the meaning of any existing code. It simply allows code that would otherwise be illegal to become legal.

int *p = arr; // assigning a pointer with an array.  Why should that work?
                  // It works, but only because of a special dispensation.

When an array decays, it decays to a pointer to a single element int [10] -> int*. It does not decay to a pointer to the array, that would be int (*p)[10].


Now, we can look at this line from your question:

int (T::*pA3)[10] = T::b; // error

Again, the class member is not relevant to understanding why this failed. The type on the left is a pointer-to-array-of-ints, not a pointer-to-int. Therefore, as we said earlier, decaying is not relevant and you need & to get the pointer-to-array-of-ints type.

A better question would be to ask why this doesn't work (Update: I see now that you did have this in your question.)

int T::*pA3 = T::b;

The right hand side looks like an array, and the left hand side is a pointer to a single element int *, and therefore you could reasonably ask: Why doesn't decay work here?

To understand why decay is difficult here, let's "undo" the syntactic sugar, and replace T::b with &(T::b[0]).

int T::*pA3 = &(T::b[0]);

I think this is the question that you're interested in. We've removed the decaying in order to focus on the real issue. This line works with non-member objects, why doesn't it work with member objects?

The simple answer is that the standard doesn't require it. Pointer-decay is a piece of syntactic sugar, and they simply didn't specify that it must work in cases like this.

Pointers-to-members are basically a little fussier than other pointers. They must point directly at the 'raw' entity as it appears in the object. (Sorry, I mean it should refer (indirectly) by encoding the offset between the start of the class and the location of this member. But I'm not very good at explaining this.) They can't point to sub-objects, such as the first element of the array, or indeed the second element of the array.

Q: Now I have a question of my own. Could pointer decay be extended to work on member arrays like this? I think it makes some sense. I'm not the only one to think of this! See this discussion for more. It's possible, and I guess there's nothing stopping a compiler from implementing it as an extension. Subobjects, including array members, are at a fixed offset from the start of the class, so this is pretty logical.

这篇关于试图理解“指向成员的指针”的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆