仅在一个构造函数上的类成员初始化程序中的隐式常量转换 [-Werror=overflow] 溢出

Posted

技术标签:

【中文标题】仅在一个构造函数上的类成员初始化程序中的隐式常量转换 [-Werror=overflow] 溢出【英文标题】:overflow in implicit constant conversion [-Werror=overflow] in class member initializer only on one constructor 【发布时间】:2020-02-25 02:33:37 【问题描述】:

有几个类似的问题,但这个问题可能(?)是由于 gcc 编译器中的错误。唯一的 const 是参数 vvalue。我已更改为 char* 并且仍然收到相同的编译器警告。

这是带有类的第三方代码(不显示命名空间等) 只显示相关部分

class Value 
public:
    ....
    Value(double value);
    Value(const char *vvalue);
    ....
private:
        struct CommentInfo 
          CommentInfo();
           ~CommentInfo();
          void setComment( const char *text );
           char *comment_;
      ;

        union ValueHolder 
          Int int_;
           UInt uint_;
           double real_;
           bool bool_;
           char *string_;
 #ifdef JSON_VALUE_USE_INTERNAL_MAP
           ValueInternalArray *array_;
          ValueInternalMap *map_;
 #else
         ObjectValues *map_;
 #endif
         value_;
        ValueType type_ : 8;
        int allocated_ : 1;     // Notes: if declared as bool, bitfield is useless.
 #ifdef JSON_VALUE_USE_INTERNAL_MAP
       unsigned int itemIsUsed_ : 1;      // used by the ValueInternalMap container.
        int memberNameIsStatic_ : 1;       // used by the ValueInternalMap container.
 #endif
        CommentInfo *comments_;
     ;

;

/// class definition
 316 Value::Value( double value )
 317    : type_( realValue )
 318    , comments_(nullptr)
 319 # ifdef JSON_VALUE_USE_INTERNAL_MAP
 320    , itemIsUsed_( 0 )
 321 #endif
 322 
 323    value_.real_ = value;
 324 
 325 
 326 Value::Value(const char *vvalue)
 327    : type_(stringValue), allocated_(true),
 328       comments_(nullptr)
 329 #ifdef JSON_VALUE_USE_INTERNAL_MAP
 330       , itemIsUsed_( 0 )
 331 #endif 
 332      
 333    value_.string_ = duplicateStringValue(vvalue);
 334      

当我们使用 -Werror -Wall 运行时,我们会收到以下错误消息,只有构造函数接受输入,而不是 cmets_ 成员的其他构造函数:

json_value.cpp:328:24: error: overflow in implicit constant conversion [-Werror=overflow]
       comments_(nullptr)
                        ^

奇怪的是,带有(双值)版本的构造函数不会出现警告。我盯着代码看了很长时间,看不出我可以改变哪里来消除这个警告。

这可能与位域有关:

 309 Value::Value( double value )
 310    : type_( realValue ),
 311    //allocated_(true), // adding this caused overflow issue
 312    //allocated_(1), // adding this caused overflow issue
 313    //allocated_(0), // this eliminates overflow issue
 314    allocated_(false), // this eliminates overflow issue
 315    comments_(nullptr)

我发现,警告与前一个类成员中的位字段有关:alocated_ 这是布尔值的 1 位。不确定代码是不好的做法还是什么。

【问题讨论】:

***.com/help/minimal-reproducible-example 【参考方案1】:

位域allocated_ 可以保存两个值。在您的实现中,它们是0-1。 See this question for why. 您正在使用true 对其进行初始化,它转换为1,它会溢出。开启-Wconversion 很好地解释了这一点:

警告:从 'int' 到 'signed char:1' 的转换会将值从 '1' 更改为 '-1' [-Wconversion]

更新:溢出警告也有这个细节。从 gcc 8.1 开始,两者都有这个细节。此第三方库似乎是 jsoncpp,并且此错误似乎已在 2015 年 1 月 24 日的提交 2bc6137a (ref) 中修复,并包含在 2015 年 2 月 11 日发布的 v1.4.0 (ref) 中。

【讨论】:

以上是关于仅在一个构造函数上的类成员初始化程序中的隐式常量转换 [-Werror=overflow] 溢出的主要内容,如果未能解决你的问题,请参考以下文章

std::array 实现上的隐式构造函数的奇怪错误

Dart中的类和单例模式

Scala中的隐式转换|理解

避免构造函数中的隐式转换。 'explicit' 关键字在这里没有帮助

boost::optional<std::string> 和 char[] 的隐式构造函数

C ++:从另一个构造函数隐式调用构造函数