C++ 草案标准 (N3337) 有以下关于指针转换的内容:
4.10 Pointer conversions
2 An rvalue of type “pointer to cv
T
,” whereT
is an object type, can be converted to an rvalue of type “pointer to cvvoid
.” The result of converting a “pointer to cvT
” to a “pointer to cvvoid
” points to the start of the storage location where the object of typeT
resides, as if the object is a most derived object (1.8) of typeT
(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 avoid*
as well asbool
.
引用声明指向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 转换都在其中。
从这里,我们学到了一些重要的东西:指针转换和 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/