constant vector

A

Alvin

Hello,

I have been experimenting with std::vector. Say I wanted to create a vector
of integers but do not want the vector to change in size or capacity. In
otherwords, it has a fixed number of elements.

To do this I declared a vector of 4 integers as:

const vector<int> pool(4);

Now, to set values of the integers I had to use const_cast as in:

for(int i = 0; i < pool.size(); i++)
{
int *n = const_cast<int*>(&pool);

*n = 50+i;
}

This will make the vector contain the numbers: 50, 51, 52, 53.

The reason for the making the vector 'const' is so that a compiler will flag
an error if the vector is modified. For example, this will produce a
compiler error (I want this error to occur):

pool.push_back(9);

Ignoring the practicality of this trivial example, is this valid?
 
V

Victor Bazarov

Alvin said:
I have been experimenting with std::vector. Say I wanted to create a vector
of integers but do not want the vector to change in size or capacity. In
otherwords, it has a fixed number of elements.

To do this I declared a vector of 4 integers as:

const vector<int> pool(4);

Now, to set values of the integers I had to use const_cast as in:

for(int i = 0; i < pool.size(); i++)
{
int *n = const_cast<int*>(&pool);

*n = 50+i;
}

This will make the vector contain the numbers: 50, 51, 52, 53.

The reason for the making the vector 'const' is so that a compiler will flag
an error if the vector is modified. For example, this will produce a
compiler error (I want this error to occur):

pool.push_back(9);

Ignoring the practicality of this trivial example, is this valid?


It's probably valid. 'std::vector' allocates its contents from free store
and thus should have no particular issue with const_cast. However, if I
were to implement a vector with constant size, I'd probably wrapped the
'std::vector' in my own interface that would not have size-changing ops
available instead of declaring the vector 'const' and then tweaking it
using 'const_cast'...

V
 
D

David Harmon

On Thu, 05 May 2005 18:53:07 GMT in comp.lang.c++, Alvin
const vector<int> pool(4); ....
int *n = const_cast<int*>(&pool); ....
Ignoring the practicality of this trivial example, is this valid?


No. When you declare the vector const, the compiler is free to
implement it in such a way that modifying it after it is constructed
may not work.

Use one of the vector constructors that fully initializes it in the
form you want at the time of construction; or build a not-const vector
and create a const reference to it for public use.
 
A

Alf P. Steinbach

* Alvin:
I have been experimenting with std::vector. Say I wanted to create a vector
of integers but do not want the vector to change in size or capacity. In
otherwords, it has a fixed number of elements.

To do this I declared a vector of 4 integers as:

const vector<int> pool(4);

Now, to set values of the integers I had to use const_cast as in:

for(int i = 0; i < pool.size(); i++)
{
int *n = const_cast<int*>(&pool);

*n = 50+i;
}

This will make the vector contain the numbers: 50, 51, 52, 53.

The reason for the making the vector 'const' is so that a compiler will flag
an error if the vector is modified. For example, this will produce a
compiler error (I want this error to occur):

pool.push_back(9);

Ignoring the practicality of this trivial example, is this valid?


No.

You can only (formally) cast away const for something that wasn't const
in the first place.

The simplest way to do the above is to write a function that returns a vector
which you can then use as initializer, or to use a function or functor class
instead of a vector.

More advanced, you can write an iterator class and use that to initialize the
vector.

More advanced still, you can generalize that iterator class to iterate using
any client code function or functor class to provide the values.
 
A

Abecedarian

Alvin said:
The reason for the making the vector 'const' is so that a compiler will flag
an error if the vector is modified. For example, this will produce a
compiler error (I want this error to occur):

pool.push_back(9);

Why don't you write a small wrapper over std::vector that implements
the behavior you want?

::A::
 
A

Alvin

Alvin said:
Hello,

I have been experimenting with std::vector. Say I wanted to create a
vector of integers but do not want the vector to change in size or
capacity. In otherwords, it has a fixed number of elements.

To do this I declared a vector of 4 integers as:

const vector<int> pool(4);

Now, to set values of the integers I had to use const_cast as in:

for(int i = 0; i < pool.size(); i++)
{
int *n = const_cast<int*>(&pool);

*n = 50+i;
}

This will make the vector contain the numbers: 50, 51, 52, 53.

The reason for the making the vector 'const' is so that a compiler will
flag an error if the vector is modified. For example, this will produce a
compiler error (I want this error to occur):

pool.push_back(9);

Ignoring the practicality of this trivial example, is this valid?


Thank you everyone for your comments. Looks like the proper solution would
be to create a wrapper around std::vector that exposes only the desired
methods. But I will look into the boost::array and see what that offers.
Actually, I know very little about Boost, but it seems like a very
promising extension.

Alvin
 
D

Default User

__PPS__ said:
or if you don't, use boost.array. It is the same as std::tr1:array,
AFAIK

Please quote enough of the previous message to provide context for your
replies. To do so using the Google interface, click on "show options"
and use the Reply shown in the expanded header.




Brian
 
I

Ivan Vecerina

Alvin said:
I have been experimenting with std::vector. Say I wanted to create a
vector
of integers but do not want the vector to change in size or capacity. In
otherwords, it has a fixed number of elements.

To do this I declared a vector of 4 integers as:

const vector<int> pool(4);

Now, to set values of the integers I had to use const_cast as in:

for(int i = 0; i < pool.size(); i++)
{
int *n = const_cast<int*>(&pool);

*n = 50+i;
}

Poor choice IMO, and in theory could lead to undefined behavior
(e.g. an std::vector could implement something similar to the
small string optimization used by some std::string implementations).
The reason for the making the vector 'const' is so that a compiler will
flag
an error if the vector is modified. For example, this will produce a
compiler error (I want this error to occur):

pool.push_back(9);

Ignoring the practicality of this trivial example, is this valid?

Better options would be to:
a) create a function that returns the vector
b) initialize the vector from an array

Here's an example for b):
int data[4] = { 50,51,52,53 };
const vector<int> pool( data, data+4 );


Ivan
 
P

__PPS__

Better options would be to:
a) create a function that returns the vector
b) initialize the vector from an array

Here's an example for b):
int data[4] = { 50,51,52,53 };
const vector<int> pool( data, data+4 );


Ivan
--

boost::array<int, 4> pool = {50,51,52,53};

??
 
I

Ivan Vecerina

__PPS__ said:
Better options would be to:
a) create a function that returns the vector
b) initialize the vector from an array

Here's an example for b):
int data[4] = { 50,51,52,53 };
const vector<int> pool( data, data+4 );

boost::array<int, 4> pool = {50,51,52,53};

Sure, but this is pretty much the equivalent of
the first code line above.
It doesn't replace the second line if it is a
vector<int> that is then actually required.

Ivan
 
P

__PPS__

Ivan said:
__PPS__ said:
Better options would be to:
a) create a function that returns the vector
b) initialize the vector from an array

Here's an example for b):
int data[4] = { 50,51,52,53 };
const vector<int> pool( data, data+4 );

boost::array<int, 4> pool = {50,51,52,53};

Sure, but this is pretty much the equivalent of
the first code line above.
It doesn't replace the second line if it is a
vector<int> that is then actually required.


Yes it looks like the first line of code; Yes it doesn't replace the
second line - you just don't need it anymore. It creates a constant
size array of 4 integers.
 
I

Ioannis Vranos

Alvin said:
I have been experimenting with std::vector. Say I wanted to create a vector
of integers but do not want the vector to change in size or capacity. In
otherwords, it has a fixed number of elements.

To do this I declared a vector of 4 integers as:

const vector<int> pool(4);

Now, to set values of the integers I had to use const_cast as in:

for(int i = 0; i < pool.size(); i++)
{
int *n = const_cast<int*>(&pool);

*n = 50+i;
}

This will make the vector contain the numbers: 50, 51, 52, 53.

The reason for the making the vector 'const' is so that a compiler will flag
an error if the vector is modified. For example, this will produce a
compiler error (I want this error to occur):

pool.push_back(9);

Ignoring the practicality of this trivial example, is this valid?



const vector creates indeed a const vector (it can;t be modified). If you want to remove
its constness you can do:


#include <vector>

int main()
{
using namespace std;

const vector<int> pool(4);

//...

vector<int> *pvec= const_cast<vector<int> *>(&pool);


for(vector<int>::size_type i = 0; i < pool.size(); ++i)
(*pvec) = 50+i;
}



However this is tricky, and I think it is undefined behaviour for an object originally
declared as const (I think it is about to be used for originally non-const objects, from
inside a function with const arguments for example).
 
P

__PPS__

all this casting constness away is a bad decision - probably the
original author should reconsider if it must be const vector (or better
boost::array) at all.
don't do things like this, you cannot write/modify into const obects by
casting away constness - it leads to undefined behavior. As someone
already noted, compilers are free to optimize const objects in some
way, so that it could be impossible to modify objects...
http://www.google.ca/search?hl=en&q=const_cast&btnG=Google+Search&meta=

"..Depending on the type of the referenced object, a write operation
through the resulting pointer, reference, or pointer to data member
might produce undefined behavior."
 
I

Ivan Vecerina

__PPS__ said:
Ivan said:
__PPS__ said:
Better options would be to:
a) create a function that returns the vector
b) initialize the vector from an array

Here's an example for b):
int data[4] = { 50,51,52,53 };
const vector<int> pool( data, data+4 );

boost::array<int, 4> pool = {50,51,52,53};

Sure, but this is pretty much the equivalent of
the first code line above.
It doesn't replace the second line if it is a
vector<int> that is then actually required.

Yes it looks like the first line of code; Yes it doesn't replace the
second line - you just don't need it anymore. It creates a constant
size array of 4 integers.
Same for: int data[4];

I am fully aware of the advantages of boost::array
over C-style array, but I do not think that they
are relevant in the context of the OP question.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,202
Messages
2,571,057
Members
47,667
Latest member
DaniloB294

Latest Threads

Top