使用不同整数类型的std :: vector <size_t>总是安全的吗?

时间:2016-12-19 02:09:57

标签: c++

尝试接收具有未知大值的向量我想出了一个我认为完全错误的解决方案:我认为std::vector<size_t>的元素首先分配给一个小值然后分配给一个大值可能存在错误或数据丢失,因为已经设置了整个向量的类型并且已经安排了内存中的一些空间。

但是以下代码有效:

#include<vector>
#include<iostream>
#include<typeinfo>

int main(){

    std::vector<size_t> vec;

    // Fixing size and adding small number which 
    // I suppose would set type as a small one, 
    // i.e. int 
    vec.resize(2);
    int i = 0;
    std::fill(vec.begin(),vec.end(),i);    

    // add a big number that should not fit smaller type
    unsigned long long bignum = 18446744073709551614;
    vec.push_back(bignum);

    std::cout<<vec[0]<<" "<<vec[1]<<" "<<vec[2]<<std::endl;
    std::cout<<typeid(vec[0]).name()<<std::endl
    <<typeid(vec[1]).name()<<std::endl<<typeid(vec[2]).name()<<std::endl;

    // cell 0 was already initialized with int, trying to make oveflow
    vec[0] = 18446744073709551613;

    std::cout<<vec[0]<<" "<<vec[1]<<" "<<vec[2]<<std::endl;
    std::cout<<typeid(vec[0]).name()<<std::endl
    <<typeid(vec[1]).name()<<std::endl<<typeid(vec[2]).name()<<std::endl;

    return 1;   
}

但是,输出不包含类型名称,可能是因为我的编译器:

$ ./a.out
0 0 18446744073709551614
m
m
m
18446744073709551613 0 18446744073709551614
m
m
m

所有编译器都安全吗?当我不知道使用的整数类型时,我可以自由地使用vector::<size_t>(发送到函数等)吗?

3 个答案:

答案 0 :(得分:4)

不,这不安全。

这只是工作,因为你放了一个int >= 0size_tunsigned因此,如果您尝试设置负值,则会有negative_value % 2**n,其中n是用于表示无符号类型的位数。

向量中的元素是size_t。当您使用i填充它时,您要求编译器将int强制转换为size_t。这不是“安全的”。

vec[0] = 18446744073709551613;

这是安全的,因为vec [0]是size_t

请注意size_t旨在处理...大小。因此,可以处理size_t的最大值不固定。如果你想要股票整数。使用<cstdint>

答案 1 :(得分:4)

除了@Stargateur的答案之外,最好的便携式赌注是intmax_tuintmax_t。它们被保证是平台上可用的最大整数类型。

可能还有编译器特定的扩展名,例如__int128_tThis answer提供了有关gcc中128位内置函数的一些信息。请注意std::intmax_t将是64位。

答案 2 :(得分:4)

vector<size_t>表示其条目均为size_t的向量。如果您尝试存储的值不是size_t,则会在存储之前将其隐式转换为size_t。如果原始值是[0SIZE_MAX]范围之外的整数,则可能会导致数据丢失。

你的问题表明你想象矢量存储了各种不同类型的对象,但这种情况不会发生。

注意:size_t通常表示可能的最大可分配单元的大小。也许最好使用更能反映您所存储的值的来源的类型,例如uint64_t