20

我对一些 C++ 代码进行了一些重度重构,并发现了许多由我不知道的隐式转换引起的错误。

例子

struct A *a();

bool b() {
    return a();
}

void c() {
    int64_t const d(b());
}

问题

  1. b,返回类型a被默默地转换为bool
  2. c中,返回的值b被默默地提升为int64_t

问题

如何接收原始类型之间隐式转换的警告或错误

笔记

  1. 的使用-Wconversion似乎只选择了几个与上面示例无关的任意转换。
  2. BOOST_STRONG_TYPEDEF不是一个选项(我的类型需要是 POD,因为它们用于磁盘结构)。
  3. C 也很有趣,但是这个问题与 C++ 代码库有关。
4

6 回答 6

7

C++ 编程语言,第 3 版,附录 C.6,即“隐式类型转换”中,Bjarne Stroustrup 将转换分类为提升转换:第一个“保留值”(这是你的情况 2),第二个没有(情况1)。

关于转换,他说“基本类型可以通过多种方式相互转换。在我看来,允许进行太多转换。” 和“编译器可以警告许多有问题的转换。幸运的是,许多编译器实际上会这样做。”

另一边的促销是安全的,似乎编译器不应该对他们发出警告。

编译器警告通常不是强制性的。通常在 C++草案和最终的 ANSI 文档中报告说“实施者应该发出警告”:如果需要,您可以自己检查以获取更多信息。

已编辑:添加了 C++11 注意:

The C++ programming language, 4th edition中,第 3 版的附录再次被报道并扩展为第 10.5 节“隐式类型转换”。

由于之前的考虑相同,C++11 更精确地定义了“缩小转换”并添加了 {}-initializer notation (6.3.5),截断会导致编译错误。

于 2014-01-29T09:08:34.090 回答
2

如果您使用 gcc,您是否尝试过 -Wall -Wextra 基本上检查此页面
http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html

如果不是 GCC,请发布编译器详细信息。

于 2010-12-18T08:10:15.533 回答
2

A*Microsoft Visual C++ 会针对从到的缩小转换发出警告bool

请参阅编译器警告 C4800

另一方面,促销不是“危险”的转换,因为不可能丢失数据。

编辑:演示

C:\Users\Ben>copy con test.cpp
bool f( void ) { return new int(); }
^Z
        1 file(s) copied.

C:\Users\Ben>cl /c /W4 test.cpp
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.30319.01 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

test.cpp
test.cpp(1) : warning C4800: 'int *' : forcing value to bool 'true' or 'false' (
performance warning)
于 2010-12-18T22:43:54.110 回答
1

据我了解,您无法控制原始类型之间的隐式转换:它是标准强制要求的,任何兼容的编译器都会默默地执行它。

你确定像 BOOST_STRONG_TYPEDEF 这样的方法不能解决你的问题吗?一个没有虚成员函数而只有一个原始数据成员的类基本上只不过是一种 POD 数据类型。您可以遵循相同的方法,只允许转换为基本原始类型;例子:

#include <iostream>
#include <stdexcept>

struct controlled_int {
  // allow creation from int
  controlled_int(int x) : value_(x) { };
  controlled_int& operator=(int x) { value_ = x; return *this; };
  // disallow assignment from bool; you might want to use BOOST_STATIC_ASSERT instead
  controlled_int& operator=(bool b) { throw std::logic_error("Invalid assignment of bool to controlled_int"); return *this; };

  // creation from bool shouldn't happen silently
  explicit controlled_int(bool b) : value_(b) { };

  // conversion to int is allowed
  operator int() { return value_; };

  // conversion to bool errors out; you might want to use BOOST_STATIC_ASSERT instead

  operator bool() { throw std::logic_error("Invalid conversion of controlled_int to bool"); };

  private:
    int value_;
};

int main()
{
  controlled_int a(42);

  // This errors out:
  // bool b = a;

  // This gives an error as well:
  //a = true;

  std::cout << "Size of controlled_int: " << sizeof(a) << std::endl;
  std::cout << "Size of int: " << sizeof(int) << std::endl;

  return 0;
}
于 2010-12-18T08:50:21.553 回答
1

您可以使用一种可用的静态分析工具、诸如 clint 或 C++ 等价物的程序,或一种商业上可用的工具。许多这些工具可以挑选出有问题的隐式转换。

于 2010-12-18T21:43:41.513 回答
0

编写自定义 clang 插件来诊断您的问题。我们在 LibreOffice 代码中做了很多这样的事情。如果您想在http://cgit.freedesktop.org/libreoffice/core/tree/compilerplugins/clang获得灵感,请来浏览我们的资源

于 2015-06-14T11:28:48.017 回答