考虑以下 C++ 代码:
#include <cstdint>
#include <vector>
template<typename BaseType>
class InitInt {
public:
using base_type = BaseType;
private:
BaseType value_;
public:
InitInt() : value_(0) {}
explicit InitInt(BaseType value) : value_(value) {}
InitInt(
const InitInt<BaseType>& other)
: value_(other.get()) {}
const BaseType& get() const { return value_; }
};
using InitInt16 = InitInt<int16_t>;
class IntInt16PairVector {
public:
std::vector<std::pair<InitInt16, InitInt16>> m;
};
void f(IntInt16PairVector& v) {
v.m = {{InitInt16(0), InitInt16(0)}};
}
int main(void) {
IntInt16PairVector v;
f(v);
}
当使用带有标志
-O3
和 -Wall
的 GCC 12.3.0 编译此代码时,它会警告在函数中使用未初始化的值 f()
。
In copy constructor ‘InitInt<BaseType>::InitInt(const InitInt<BaseType>&) [with BaseType = short int]’,
inlined from ‘std::pair<_T1, _T2>::pair(const std::pair<_T1, _T2>&) [with _T1 = InitInt<short int>; _T2 = InitInt<short int>]’ at /usr/lib/gcc/x86_64-pc-linux-gnu/12.3.0/include/c++/bits/stl_pair.h:195:17,
inlined from ‘void std::_Construct(_Tp*, _Args&& ...) [with _Tp = pair<InitInt<short int>, InitInt<short int> >; _Args = {const pair<InitInt<short int>, InitInt<short int> >&}]’ at /usr/lib/gcc/x86_64-pc-linux-gnu/12.3.0/include/c++/bits/stl_construct.h:119:7,
inlined from ‘_ForwardIterator std::__do_uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = const pair<InitInt<short int>, InitInt<short int> >*; _ForwardIterator = pair<InitInt<short int>, InitInt<short int> >*]’ at /usr/lib/gcc/x86_64-pc-linux-gnu/12.3.0/include/c++/bits/stl_uninitialized.h:120:21,
inlined from ‘static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = const std::pair<InitInt<short int>, InitInt<short int> >*; _ForwardIterator = std::pair<InitInt<short int>, InitInt<short int> >*; bool _TrivialValueTypes = false]’ at /usr/lib/gcc/x86_64-pc-linux-gnu/12.3.0/include/c++/bits/stl_uninitialized.h:137:32,
inlined from ‘_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = const pair<InitInt<short int>, InitInt<short int> >*; _ForwardIterator = pair<InitInt<short int>, InitInt<short int> >*]’ at /usr/lib/gcc/x86_64-pc-linux-gnu/12.3.0/include/c++/bits/stl_uninitialized.h:185:15,
inlined from ‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, allocator<_Tp>&) [with _InputIterator = const pair<InitInt<short int>, InitInt<short int> >*; _ForwardIterator = pair<InitInt<short int>, InitInt<short int> >*; _Tp = pair<InitInt<short int>, InitInt<short int> >]’ at /usr/lib/gcc/x86_64-pc-linux-gnu/12.3.0/include/c++/bits/stl_uninitialized.h:372:37,
inlined from ‘void std::vector<_Tp, _Alloc>::_M_assign_aux(_ForwardIterator, _ForwardIterator, std::forward_iterator_tag) [with _ForwardIterator = const std::pair<InitInt<short int>, InitInt<short int> >*; _Tp = std::pair<InitInt<short int>, InitInt<short int> >; _Alloc = std::allocator<std::pair<InitInt<short int>, InitInt<short int> > >]’ at /usr/lib/gcc/x86_64-pc-linux-gnu/12.3.0/include/c++/bits/vector.tcc:339:35,
inlined from ‘std::vector<_Tp, _Alloc>& std::vector<_Tp, _Alloc>::operator=(std::initializer_list<_Tp>) [with _Tp = std::pair<InitInt<short int>, InitInt<short int> >; _Alloc = std::allocator<std::pair<InitInt<short int>, InitInt<short int> > >]’ at /usr/lib/gcc/x86_64-pc-linux-gnu/12.3.0/include/c++/bits/stl_vector.h:785:21,
inlined from ‘void f(IntInt16PairVector&)’ at test.cpp:32:37:
test.cpp:19:11: warning: ‘<anonymous>’ may be used uninitialized [-Wmaybe-uninitialized]
19 | : value_(other.get()) {}
| ^~~~~~~~~~~~~~~~~~~
test.cpp: In function ‘void f(IntInt16PairVector&)’:
test.cpp:32:44: note: ‘<anonymous>’ declared here
32 | v.m = {{InitInt16(0), InitInt16(0)}};
| ^
我认为此警告是由于使用未初始化的副本将初始值设定项列表分配到向量中造成的。我怎样才能删除这个?
警告来自 main 中的
v
,它尚未初始化。为什么 GCC 决定发出警告,我并不是 100% 清楚,但我怀疑,当您提供自己的复制构造函数时,GCC 以某种方式选择假设,您可能会在那里做一些有趣的事情。您有两种选择来消除警告:
v
来初始化 main 中的 IntInt16PairVector v{};
,注意空大括号。