I'm reading the g++ implementations of std::shared_ptr and std::weak_ptr, and I cannot figure out why sizeof(std::_Sp_counted_base<__gnu_cxx::__default_lock_policy>) is not 8.
In bits/shared_ptr_base.h:
std::shared_ptr<_Tp>derives fromstd::__shared_ptr<_Tp>.std::__shared_ptr<_Tp>has anelement_type*and a__shared_count<_Lp>._Lprepresents a lock policy.std::__shared_count<_Lp>is a wrapper ofstd::_Sp_counted_base<_Lp>*.
Then:
std::_Sp_counted_base<_Lp>derives fromstd::_Mutex_base<_Lp>. Sincestd::_Mutex_base<_Lp>is an empty base class when_Lpis not__gnu_cxx::_S_mutexand the default value is__gnu_cxx::_S_atomic, it will not contribute tostd::_Sp_counted_base<_Lp>'s size in my case.- There are only 2 fields in
std::_Sp_counted_base<_Lp>'s definition:_M_use_countand_M_weak_count. They are both_Atomic_word, which is a type alias ofint. - So
std::_Sp_counted_base<__gnu_cxx::__default_lock_policy>should be 8 bytes?
https://godbolt.org/z/8dK7G1ar1
#include <iostream>
#include <memory>
#include <iomanip>
template <typename... Ts>
void println(Ts &&... xs) {
std::cout << std::boolalpha;
((std::cout << xs << " "), ...);
std::cout << "\n";
}
int main() {
static_assert(__gnu_cxx::__default_lock_policy == __gnu_cxx::_S_atomic);
println("_Sp_counted_base ", sizeof(std::_Sp_counted_base<__gnu_cxx::__default_lock_policy>));
println("_Atomic_word ", sizeof(_Atomic_word));
println("_Mutex_base ", sizeof(std::_Mutex_base<__gnu_cxx::_S_atomic>));
println("_Sp_counted_base<a>", sizeof(std::_Sp_counted_base<__gnu_cxx::_S_atomic>));
println("_Sp_counted_base<m>", sizeof(std::_Sp_counted_base<__gnu_cxx::_S_mutex>));
println("_Sp_counted_base<s>", sizeof(std::_Sp_counted_base<__gnu_cxx::_S_single>));
}
I compiled the code with gcc 13.2. sizeof(std::_Sp_counted_base<__gnu_cxx::__default_lock_policy>)) is 16 in 64-bit mode and 12 in 32-bit mode. Is there a hidden long or pointer field that I missed? The source I'm reading is g++ 14.0.1, but even when I change the compiler version, the result stays the same.