Slowpoke
Slowpoke

Reputation: 1079

Is it always safe to use std::vector<size_t> with different integer types?

Trying to receive a vector with unknown big values I came up with a solution I thought to be entirely wrong: I supposed when an element of the std::vector<size_t> is assigned first to a small value and then to a big one there could be an error or data loss because the type for the entire vector was already set and some space in memory was arranged.

However the following code works:

#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;   
}

However, the output does not contain type names, maybe because of my compiler:

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

So is it safe for all compilers and can I freely operate with vector::<size_t> (send to functions, etc) when I don't know the integer types used?

Upvotes: 2

Views: 4768

Answers (3)

Stargateur
Stargateur

Reputation: 26727

No, it's not safe.

It's only work because you put a int >= 0. size_t is unsigned so if you try to put negative value you will have negative_value % 2**n where n is the number of bits used to represent the unsigned type.


The element in your vector are size_t. When you fill it with i, you ask to the compiler to cast a int into a size_t. This is not "safe".


vec[0] = 18446744073709551613;

And here this is safe because vec[0] is a size_t.


Beware that size_t is designed to handle... size. So the max value that can handle a size_t is not fixed. If you want stock integer. Use <cstdint>.

Upvotes: 4

Incomputable
Incomputable

Reputation: 2208

additionally to the answer by @Stargateur, the best portable bet is intmax_t and uintmax_t. They are guaranteed to be the biggest integer types available on the platform.

There might also be compiler specific extensions, such as __int128_t. This answer gives some information about 128 bit builtins in the gcc. Do note that std::intmax_t will stll be 64 bit.

Upvotes: 4

M.M
M.M

Reputation: 141618

vector<size_t> means a vector whose entries are all size_t. If you try to store a value that is not a size_t, it will be implicitly converted to size_t before being stored. This could involve data loss if the original value was an integer outside the range of [0, SIZE_MAX].

Your question suggests that you imagine the vector is storing objects of various different types, but that does not happen.

Note: size_t typically represents the size of the largest possible allocatable unit. Perhaps it would be better to use a type that more reflects the source of values you are storing, e.g. uint64_t.

Upvotes: 4

Related Questions