繁体   English   中英

使用 `emplace_back` 而不是 `push_back` 时没有缩小警告

[英]No narrowing warnings when using `emplace_back` instead of `push_back`

我的同事遇到了emplace_back的意外问题,我正试图解决这个问题。 以下test.cpp是重现该问题的最小示例:

#include <vector>                                                                                                                                                                                                  
class A {
 public:
  explicit A(int /*unused*/) {}
};
int main() {
  double foo = 4.5;
  std::vector<A> a_vec{};
  a_vec.emplace_back(foo); // No warning with Wconversion
  A a(foo); // Gives compiler warning with Wconversion as expected
}

使用 g++ 8.3.0 编译会产生以下警告:

$ g++ -Wconversion test.cpp -o test
test.cpp: In function ‘int main()’:
test.cpp:10:10: warning: conversion from ‘double’ to ‘int’ may change value [-Wfloat-conversion]
   A a(bar); // Gives compiler warning with Wconversion as expected

因此,在构造简单的 object 时会捕获隐式转换,但在调用emplace_back时不会捕获。

为什么emplace_back没有警告?

这是默认分配器如何构造A结果。 当您执行A a{foo, bar}时,您正在使用列表初始化,并且需要进行缩小转换才能发出诊断。 使用默认分配器,它使用

::new (static_cast<void*>(p)) T(std::forward<Args>(args)...)

其中p是指向向量数据元素的指针, T是向量的value_type 在这里,他们使用括号而不是大括号,并且允许使用括号缩小转换,因此您不会看到诊断消息。

如果您编写了自己的分配器

::new (static_cast<void*>(p)) T{std::forward<Args>(args)...}

然后你会得到警告。

为了获得警告,您需要编译:

$ g++ -Wsystem-headers -Wconversion test.cpp -o test
In file included from /usr/include/c++/8/vector:60,
                 from test.cpp:1:
/usr/include/c++/8/bits/stl_algobase.h: In function ‘constexpr int std::__lg(int)’:
/usr/include/c++/8/bits/stl_algobase.h:1001:44: warning: conversion from ‘long unsigned int’ to ‘int’ may change value [-Wconversion]
   { return sizeof(int) * __CHAR_BIT__  - 1 - __builtin_clz(__n); }
                                            ^
/usr/include/c++/8/bits/stl_algobase.h: In function ‘constexpr unsigned int std::__lg(unsigned int)’:
/usr/include/c++/8/bits/stl_algobase.h:1005:44: warning: conversion from ‘long unsigned int’ to ‘unsigned int’ may change value [-Wconversion]
   { return sizeof(int) * __CHAR_BIT__  - 1 - __builtin_clz(__n); }
                                            ^
In file included from /usr/include/x86_64-linux-gnu/c++/8/bits/c++allocator.h:33,
                 from /usr/include/c++/8/bits/allocator.h:46,
                 from /usr/include/c++/8/vector:61,
                 from test.cpp:1:
/usr/include/c++/8/ext/new_allocator.h: In instantiation of ‘void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = A; _Args = {double&}; _Tp = A]’:
/usr/include/c++/8/bits/alloc_traits.h:475:4:   required from ‘static void std::allocator_traits<std::allocator<_Tp1> >::construct(std::allocator_traits<std::allocator<_Tp1> >::allocator_type&, _Up*, _Args&& ...) [with _Up = A; _Args = {double&}; _Tp = A; std::allocator_traits<std::allocator<_Tp1> >::allocator_type = std::allocator<A>]’
/usr/include/c++/8/bits/vector.tcc:103:30:   required from ‘void std::vector<_Tp, _Alloc>::emplace_back(_Args&& ...) [with _Args = {double&}; _Tp = A; _Alloc = std::allocator<A>]’
test.cpp:9:25:   required from here
/usr/include/c++/8/ext/new_allocator.h:136:4: warning: conversion from ‘double’ to ‘int’ may change value [-Wfloat-conversion]
  { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }

警告不再那么清楚,因为它发生在系统 header 中。 请注意,仅使用-Wsystem-headers标志是不够的,需要同时使用-Wsystem-headers-Wconversion才能捕捉到这一点。

push_back的情况下,使用-Wnarrowing来获得警告就足够了。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM