调用构造函数时,你有多明确?

时间:2014-09-24 15:53:15

标签: c++ c++11

我有这个班级

struct foo
{
    explicit foo(const std::uint32_t& x, const std::uint32_t& y);
};

和方法

int main()
{
    std::int32_t x = -1;
    std::int32_t y = -1;
    foo f(x, y);
}

在我的编译器(MSVC2012)上,这将编译并运行包含无符号类型的值xy。我没想到会这样,但由于类型不匹配而期待编译错误。

我错过了什么?

3 个答案:

答案 0 :(得分:7)

你运气不好,标准确实允许通过为常量引用传递的参数创建匿名临时值,将signed隐式转换为unsigned。

(请注意,对于非常量引用,情况并非如此)。

如果您使用的是C ++ 11,最好的办法是使用

删除构造函数
foo(const std::int32_t& x, const std::int32_t& y) = delete;

Pre C ++ 11你可以使这个构造函数private而不是定义它。而不是老式的不可复制的习语。

MSVC2012是一种中途的C ++ 03 / C ++ 11编译器。它实现了一些C ++ 11功能,但没有实现其他功能。遗憾的是删除构造函数是支持的功能之一,因此private isation方法是您可以使用的最佳方法。

答案 1 :(得分:0)

实际上,您应该使用至少会发出警告的新大括号初始化语法foo f{x, y}。之后,您可以将编译器配置为将警告视为错误并相应地处理它们,因为良好的代码通常也应该消除警告(因为如果您想要转换发生,您应该使用< strong>显性演员)。

答案 2 :(得分:0)

explicit不会阻止使用构造函数参数进行隐式转换(这在绑定引用时明显发生);它可以防止隐式构建。

void bar(foo);
int main()
{
   foo f({0, 0}); // doesn't matter that the arguments are implicitly converted

   bar({0, 0});   // error - implicit conversion required here to pass a foo
   bar(f);        // crucially, ok because argument requires no conv. construction
}