关于std::vector类型使用下标运算符取值出错的研究

问题提出

std::vectorv(1,true);
void* p = &v[0];// 此时p指向的内存转成bool类型是false
但是
std::vector v2(2,1);
void* p3 = &v2[0];// 此时p指向的内存转成int类型时,值正常

分析

1.一般类型的vector使用下标运算符时

   _NODISCARD _Ty& operator[](const size_type _Pos) {
		auto& _My_data = _Mypair._Myval2;
。。。
		return _My_data._Myfirst[_Pos];
	}

2.继续分析_My_data._Myfirst[_Pos];

1.因为auto& _My_data = _Mypair._Myval2;所以只要分析_Mypair._Myval2._Myfirst[_Pos];即可
2._Mypair定义为_Compressed_pair<_Alty, _Scary_val> _Mypair;
3._Scary_val类型就是_Vector_val<bool _Test, class _Ty1, class _Ty2>
4.这个_Vector_val的特化类型就是_Myval2,同时_Vector_val里面定义了_Myfirst,这就是前面下标运算符用到的指针,那么这个指针是什么类型呢,继续往下看
5.看声明,pointer _Myfirst; // pointer to beginning of array
6.再看声明,using pointer = typename _Val_types::pointer;所以先找到_Val_types类型,再找到这个pointer类型即可
7._Val_types为_Vector_val的特化,所以我们回到_Vector_val的特化,再看特化的类型,它是conditional_t的特化版本。

_Vector_val的特化如下

   using _Scary_val = _Vector_val<conditional_t<_Is_simple_alloc_v<_Alty>, _Simple_types<_Ty>,
			_Vec_iter_types<_Ty, typename _Alty_traits::size_type, typename _Alty_traits::difference_type,
    			typename _Alty_traits::pointer, typename _Alty_traits::const_pointer, _Ty&, const _Ty&>>>;

8.找到conditional_t的定义,using conditional_t = typename conditional<_Test, _Ty1, _Ty2>::type;
9.再找到conditional的定义
template <bool _Test, class _Ty1, class _Ty2>
struct conditional { // Choose _Ty1 if _Test is true, and _Ty2 otherwise
using type = _Ty1;
};
10.所以conditional_t的类型即为conditional特化时,第二个模板参数类型,也就是conditional_t特化时的第二个模板参数类型,回到_Vector_val的特化,可以看到这个类型是_Simple_types<_Ty>

11.进到Simple_types<_Ty>的定义
using pointer = value_type*; 等价于using pointer = _Ty*
12.这个_Ty类型就是我们构造vector对象时传入的模板参数类型,所以pointer就是对应的指针,也就相当于数组指针(这一点可以到vector构造时调用的 _Construct_n_copies_of_ty()里面得到证明)
13.所以最后得出结论:一般类型的vector下标运算结果是这种类型的值引用

3.下面分析bool类型的vector使用下标运算返回的类型

1.进到定义

   _NODISCARD reference operator[](size_type _Off) {
		iterator _It = begin();
		_It._Advance(_Off);
		return *_It;
	}

2.reference定义如下

		   template <class _Alvbase_wrapped>
		   class _Vb_reference : public _Vb_iter_base<_Alvbase_wrapped> { // reference to a bit within a base word
		   。。。。
		   }

3.从定义可以看出reference是一个类类型,这个类是迭代器的叔叔类,所以在1中实际上发生了隐式类型转换
4.那么这个reference的值是怎么计算的呢,这一点没有去深究

4.结论

bool类型存入vector,再用下标运算符取出来的是reference类的拷贝,再使用取址符得到的是这个类的地址,没有参考意义。而普通类型用下标运算符算出来的就是这个类型的值引用,因此与期望一致

©️2020 CSDN 皮肤主题: 大白 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值