size_t,ptrdiff_t和std :: vector :: size()

时间:2011-07-19 02:37:40

标签: c++

我认为用于存储指针之间差异的正确类型是ptrdiff_t

因此,我对我的STL(msvc 2010)实现它的std::vector::size()函数的方式感到困惑。返回类型是size_t(根据我的理解,这是标准规定的),但它是按指针的差异计算的:

// _Mylast, _Myfirst are of type pointer
// size_type, pointer are inherited from allocator<_Ty>
size_type size() const 
{
    return (this->_Mylast - this->_Myfirst);
}

显然,为了准确确定size_typepointer的类型,还会进行一些元魔术。为了“确定”它们是什么类型我检查了这个:

bool bs = std::is_same<size_t, std::vector<int>::size_type>::value;
bool bp = std::is_same<int * , std::vector<int>::pointer>::value;
// both bs and bp evaluate as true, therefore:
//   size_type is just size_t
//   pointer is just int*

使用/Wall汇总以下内容可为signed-to-unsigned mismatch提供mysize2,但mysize1没有警告:

std::vector<int> myvector(100);
int *tail = &myvector[99];
int *head = &myvector[ 0];
size_t mysize1 = myvector.size();
size_t mysize2 = (tail - head + 1);

mysize2的类型更改为ptrdiff_t会导致无效警告。 将mysize1的类型更改为ptrdiff_t会产生unsigned-to-signed mismatch

显然我错过了什么......

编辑:我不是要问如何使用演员或#pragma disable(xxx)来抑制警告。我担心的问题是size_tptrdiff_t可能有不同的允许范围(它们在我的机器上)。

考虑std::vector<char>::max_size()。我的实现返回max_size等于std::numeric_limits<size_t>::max()。由于vector::size()在转换为ptrdiff_t之前正在创建size_t类型的中间值,因此此处似乎存在问题 - ptrdiff_t不足以容纳vector<char>::max_size() }。

2 个答案:

答案 0 :(得分:6)

一般来说,ptrdiff_t是一个与size_t大小相同的有符号整数类型。必须对其进行签名,以便它可以代表p1 - p2p2 - p1

在std :: vector内部的特定情况下,实现者实际上从size()派生end() - begin()。由于std :: vector(连续的,基于数组的存储)的保证,结束指针的值总是大于begin指针的值,因此不存在生成负值的风险。实际上,size_t总是能够表示比ptrdiff_t更大的正范围,因为它不必使用其一半的范围来表示负值。实际上,这意味着在这种情况下,从ptrdiff_t到size_t的强制转换是一个扩展的强制转换,它具有明确定义(并且直观明显)的结果。

另外,请注意,这不是std :: vector的唯一可能实现。它可以很容易地实现为单个指针和包含大小的size_t值,导出end()begin() + size()。该实施也将解决您的max_size()问题。实际上,max_size实际上永远不可能实现 - 它需要为程序的缓冲区分配程序的整个地址空间,不会给begin()/ end()指针,函数调用堆栈等留下空间。

答案 1 :(得分:0)

在STL中如何实现std :: vector :: size()没有错。 this-&gt; _Mylast - this-&gt; _Myfirst == vector size 仅仅是一个巧合的事实,它依赖于矢量的实现方式。

Plus MSVC STL矢量实现有一个 #pragma警告(禁用:4244),它会删除警告。