【问题标题】:What is the best way to prevent implicit conversion of integer 0 to pointer in c++防止整数0隐式转换为c ++中指针的最佳方法是什么
【发布时间】:2015-10-07 04:57:04
【问题描述】:

我试图找出防止整数 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到底是做什么的?

【问题讨论】:

  • 这里不是 C++ 专家,但我想如果你想阻止你的构造函数获取 int,你会想删除 B(int)
  • @user2357112 这不是 OP 想要的。他想避免整数常量 0 转换为空指针的特定极端情况。
  • @TheParamagneticCroissant:删除B(int) 不能解决这个问题吗?
  • @user2357112:是的,这似乎可以解决问题。我会尝试一段时间,看看会发生什么。将其作为答案,以便我接受。
  • gcc 有一个警告标志,您可以在编译时将其设置为错误。 VC++ 可能有类似的警告。

标签: c++ c++11 visual-studio-2013 implicit-conversion explicit-conversion


【解决方案1】:

删除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

您可能认为这种可能性微乎其微,可以忽略不计; 或者您可能更喜欢删除 all 构造函数, 一下子,他的论点不完全是一种类型 你认可的。例如。假设认可的类型只是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;
}

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

【讨论】:

  • 似乎不需要用nullptr 阻止显式调用;这似乎更像是一种令人不快的副作用。
  • 使用模板删除对您有用吗?模板 A(T) = 删除;我读过模板化的复制构造函数不会取消默认构造函数的资格。我也经历过。所以删除它们没有任何效果。
  • 我希望用 nullptr 调用 char*,而不是某个恰好为 0 的枚举,这就是发生在我身上的事情!我在问题中并不清楚这一点。
【解决方案2】:

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

B(int) = delete;

与采用 char * 的构造函数相比,B(0) 的匹配无疑更好。

请注意,在 C++11 之前,NULL 被指定为整数类型,即使在 C++11 及更高版本中,它仍然很可能实现为 #define NULL 0。如果您这样做,B(NULL) 将不起作用。 B(nullptr) 会起作用,但我还是会担心这是否值得做。

【讨论】:

  • 我认为这适用于我的问题。编译器查看 0 并说它也可能是 void*。然后它查看构造函数。如果找到它喜欢的 int 构造函数,则看到删除并停止。
猜你喜欢
  • 1970-01-01
  • 2020-07-23
  • 2014-11-03
  • 1970-01-01
  • 1970-01-01
  • 2010-09-12
  • 2011-03-18
  • 1970-01-01
相关资源
最近更新 更多