c++ - 为什么指向 int 的指针转换为 void* 而指向函数的指针转换为 bool?

标签 c++ pointers c++11

C++ 草案标准 (N3337) 有以下关于指针转换的内容:

4.10 Pointer conversions

2 An rvalue of type “pointer to cv T,” where T is an object type, can be converted to an rvalue of type “pointer to cv void.” The result of converting a “pointer to cv T” to a “pointer to cv void” points to the start of the storage location where the object of type T resides, as if the object is a most derived object (1.8) of type T (that is, not a base class subobject).

4.12 Boolean conversions

1 An rvalue of arithmetic, enumeration, pointer, or pointer to member type can be converted to an rvalue of type bool. A zero value, null pointer value, or null member pointer value is converted to false; any other value is converted to true

基于上述,将函数指针或指向 int 的指针转换为 void* 以及 bool.

但是,如果可以选择两者,指针应该转换为哪一个?

然后,为什么指向函数的指针会转换为 bool 而指向 int 的指针会转换为 void*

程序:

#include <iostream>
using namespace std;

void foo(const void* ptr)
{
   std::cout << "In foo(void*)" << std::endl;
}

void foo(bool b)
{
   std::cout << "In foo(bool)" << std::endl;
}

void bar()
{
}

int main()
{
   int i = 0;
   foo(&bar);
   foo(&i);
   return 0;
}

输出,使用 g++ 4.7.3:

In foo(bool)
In foo(void*)

最佳答案

Based on the above, it is perfectly OK to convert a function pointer or a pointer to an int to a void* as well as bool.

引用声明指向object的指针可以转换为cv void *。函数不是对象,这将取消转换为 cv void * 的资格,只留下 bool


However, given the choice of both, which one should a pointer convert to?

它应该通过 bool 转换为 const void *。为什么?好吧,为从过载解决 (§13.3 [over.match]/2) 开始的旅程做好准备。当然是强调我的。

But, once the candidate functions and argument lists have been identified, the selection of the best function is the same in all cases:

— First, a subset of the candidate functions (those that have the proper number of arguments and meet certain other conditions) is selected to form a set of viable functions (13.3.2).

— Then the best viable function is selected based on the implicit conversion sequences (13.3.3.1) needed to match each argument to the corresponding parameter of each viable function.

那么这些隐式转换序列呢?

让我们跳到 §13.3.3.1 [over.best.ics]/3 看看什么是隐式转换序列:

A well-formed implicit conversion sequence is one of the following forms:
— a standard conversion sequence (13.3.3.1.1),
— a user-defined conversion sequence (13.3.3.1.2), or
— an ellipsis conversion sequence (13.3.3.1.3).

我们对标准转换序列感兴趣。让我们跳到标准转换序列(§13.3.3.1.1 [over.ics.scs]):

1 Table 12 summarizes the conversions defined in Clause 4 and partitions them into four disjoint categories: Lvalue Transformation, Qualification Adjustment, Promotion, and Conversion. [ Note: These categories are orthogonal with respect to value category, cv-qualification, and data representation: the Lvalue Transformations do not change the cv-qualification or data representation of the type; the Qualification Adjustments do not change the value category or data representation of the type; and the Promotions and Conversions do not change the value category or cv-qualification of the type. — end note ]

2 [ Note: As described in Clause 4, a standard conversion sequence is either the Identity conversion by itself (that is, no conversion) or consists of one to three conversions from the other four categories.

重要的部分在/2 中。一个标准转换序列可以是一个单一的标准转换。这些标准转换列在表 12 中,如下所示。请注意,您的指针转换和 bool 转换都在其中。

Table of standard conversions and their categories and ranks

从这里,我们学到了一些重要的东西:指针转换和 bool 转换具有相同的等级。请记住,当我们前往对隐式转换序列进行排名时 (§13.3.3.2 [over.ics.rank])。

查看/4,我们看到:

Standard conversion sequences are ordered by their ranks: an Exact Match is a better conversion than a Promotion, which is a better conversion than a Conversion. Two conversion sequences with the same rank are indistinguishable unless one of the following rules applies:

— A conversion that does not convert a pointer, a pointer to member, or std::nullptr_t to bool is better than one that does.

我们以非常明确的陈述形式找到了答案。万岁!

关于c++ - 为什么指向 int 的指针转换为 void* 而指向函数的指针转换为 bool?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25552822/

相关文章:

c++ - 使用 initialization_list 导致歧义的函数重载

c++ - 如何使用OpenCV在不同的显示器上显示不同的窗口

c - 搜索数组成员之间差异的函数

c++ - 非类型模板参数可以在 STL 容器上完成吗?

c++ - 如何使用结构作为条件的操作数?

c++ - 是否可以在 C++ 中使用匿名类?

c++ - 如何使用 {} block C++ 解析文件

C++ Builder 允许将字符串与 Int 进行比较 - 为什么?

无法使用指针对没有临时变量的数组进行排序

c - 使用指针对数组进行排序,不使用任何索引变量