在c++中,防止整数0隐式转换为指针的最佳方法是什么?

What is the best way to prevent implicit conversion of integer 0 to pointer in c++

本文关键字:指针 转换 最佳 是什么 方法 c++ 整数      更新时间:2023-10-16

我试图找出最好的方法来防止整数0被隐式转换为nullptr_t,然后传递给接受指针的构造函数。显式不能做到这一点,但我可以让nullptr_t导致一个模棱两可的重载错误:

#include <typeinfo.h>
struct A {
    explicit A(char*) { }
};
struct B {
    B(nullptr_t a) = delete;
    B(char*) { }
};
int main(int argc, char* argv[])
{
    A a(0);         // darnit I compiled...
    B b1(0);        // good, fails, but with only b/c ambiguous
    B b2((char*)0); // good, succeeds
    B b3(1);        // good, fails, with correct error
}

还有比这更好的方法吗?另外,delete在这里究竟完成了什么?

删除A(int)不会阻止A(char *)被调用nullptr。因此,您也需要删除A(nullptr_t)

即使这样也不能保护你免受这附近有一些无赖阶级可从0或nullptr和隐式构造隐式转换为char *

#include <iostream>
struct A {
    A(int) = delete;
    A(std::nullptr_t) = delete;
    explicit A(char * p) {
        std::cout << "Constructed with p = " << (void *)p << std::endl;
    }
};
struct X
{
    X(long i) : _i(i) {}
    operator char *() const { return (char *)_i; }
    long _i;
};
int main()
{
    X x(0);
    A a(x);
    return 0;
}

程序打印:

Constructed with p = 0

你可能认为这种可能性遥远到可以忽略;或者您可能更喜欢删除所有构造函数,一下子,他的论点不完全是一种类型这是你认可的。例如,假设批准的类型仅为char *:

struct A {
    template<typename T>
    A(T) = delete;
    explicit A(char * p) {}
};
struct X
{
    X(long i) : _i(i) {}
    operator char *() const { return (char *)_i; }
    long _i;
};
int main()
{
    // A a0(0);
    //A a1(nullptr);
    X x(0);
    // A a2(x);
    char *p = x;
    A a3(p); // OK     
    return 0;
}

这里所有被注释掉的构造函数调用都无法编译。

如果您想阻止构造函数获取0,一种选择是删除B(int):

B(int) = delete;

这显然比接受char *的构造函数更适合B(0)

请注意,直到c++ 11, NULL被指定为整数类型,即使在c++ 11及以后的版本中,它仍然可能被实现为#define NULL 0。如果你这样做,B(NULL)将不起作用。B(nullptr)将工作,但仍然,我要警惕这是否值得做。