help about pointer copy

J

Jinjun Xu

Hi,

I have an array and I want to adjust the size (remove some elements). I use
the following code. Can you help me to check whether it's correct.

////////////// start
int *p1 = new int[oldsize];

// ....
// set the values of p1

int *p2 = p1;
p1 = new int[newsize];

// copy some values from p2 to p1
for ( i = 0; i .... )
if (....) p1 = p2;

delete []p2;

////////////// end

Suppose I have an array, e.g., int *p1 = new int[10]; is there any easy way
to reset the length of p1? (e.g, p1 becomes int[20] and the first 10
elements keep the original value).

Thank you very much in advance for your help!

JJ
 
V

Victor Bazarov

Jinjun Xu said:
I have an array and I want to adjust the size (remove some elements). I use
the following code. Can you help me to check whether it's correct.

////////////// start
int *p1 = new int[oldsize];

// ....
// set the values of p1

int *p2 = p1;
p1 = new int[newsize];

// copy some values from p2 to p1
for ( i = 0; i .... )
if (....) p1 = p2;

delete []p2;

////////////// end


Seems fine.
Suppose I have an array, e.g., int *p1 = new int[10]; is there any easy way
to reset the length of p1? (e.g, p1 becomes int[20] and the first 10
elements keep the original value).

You don't have to change anything in that case. Just think you have
fewer elements and only use as many as you think there are. And, no,
there is no "easy way to reset the length" of a dynamic array.

Victor
 
S

SaltPeter

inline...

Jinjun Xu said:
Hi,

I have an array and I want to adjust the size (remove some elements). I use
the following code. Can you help me to check whether it's correct.

////////////// start
int *p1 = new int[oldsize];

// ....
// set the values of p1

int *p2 = p1;
p1 = new int[newsize];

// copy some values from p2 to p1
for ( i = 0; i .... )
if (....) p1 = p2;

delete []p2;

////////////// end

Suppose I have an array, e.g., int *p1 = new int[10]; is there any easy way
to reset the length of p1? (e.g, p1 becomes int[20] and the first 10
elements keep the original value).

Thank you very much in advance for your help!

JJ


The easy way is to use a vector instead of an array. Arrays have a fixed
size limitation while a vector container dynamically resizes itself.
Additionally, all STL containers come equipped with powerful member
functions, iterators and algorithms to swap, sort, replace, append, push,
pop, etc...

as a simple example using a vector of integers and a display function:

#include <iostream>
#include <vector>

void display(std::vector<int>& r_v)
{
std::cout << "vector contents:" << std::endl;

std::vector<int>::iterator it;
for (it = r_v.begin(); it != r_v.end(); it++)
{
std::cout << *it << std::endl;
}
}

int main()
{
std::vector<int> vi;

// add a few elements
vi.push_back(0);
vi.push_back(1);
vi.push_back(2);

std::cout << "vector vi has " << vi.size() << " elements" << std::endl;
display(vi);

// add more elements
vi.push_back(3);
vi.push_back(4);
vi.push_back(5);

std::cout << std::endl << "vector vi has " << vi.size() << " elements"
<< std::endl;
display(vi);

std::cout << std::endl;

return 0;
}
 
D

Dave Moore

Jinjun Xu said:
Hi,

I have an array and I want to adjust the size (remove some elements). I use
the following code. Can you help me to check whether it's correct.

////////////// start
int *p1 = new int[oldsize];

// ....
// set the values of p1

int *p2 = p1;
p1 = new int[newsize];

// copy some values from p2 to p1
for ( i = 0; i .... )
if (....) p1 = p2;

delete []p2;

////////////// end

Suppose I have an array, e.g., int *p1 = new int[10]; is there any easy way
to reset the length of p1? (e.g, p1 becomes int[20] and the first 10
elements keep the original value).

No, there is not a straightforward way to do this with raw pointers.
However you can do what you want using the STL containers std::vector
or std::deque, which will grow automatically as you add data to them.
They also have functions to ensure you have enough space to hold a
minimum number of elements. However, one caveat is that each time
they grow, any pointers (or other iterators) into the container become
invalid.

HTH, Dave Moore
 
J

Jinjun Xu

Thank you guys for the reply and help! It was my first post in news group
and I am so happy to get the answer quickly and helpfully.

It seems that I should spend more time on learning using the classes in the
C++ library instead of writing from scratch by myself. My work is on
numerical computation so I need to use vector and matrix often. What I did
is to write the classes CVector and CMatrix by myself. Now I know that
vector class may help me much. Thank you.

JJ

SaltPeter said:
inline...

Jinjun Xu said:
Hi,

I have an array and I want to adjust the size (remove some elements). I use
the following code. Can you help me to check whether it's correct.

////////////// start
int *p1 = new int[oldsize];

// ....
// set the values of p1

int *p2 = p1;
p1 = new int[newsize];

// copy some values from p2 to p1
for ( i = 0; i .... )
if (....) p1 = p2;

delete []p2;

////////////// end

Suppose I have an array, e.g., int *p1 = new int[10]; is there any easy way
to reset the length of p1? (e.g, p1 becomes int[20] and the first 10
elements keep the original value).

Thank you very much in advance for your help!

JJ


The easy way is to use a vector instead of an array. Arrays have a fixed
size limitation while a vector container dynamically resizes itself.
Additionally, all STL containers come equipped with powerful member
functions, iterators and algorithms to swap, sort, replace, append, push,
pop, etc...

as a simple example using a vector of integers and a display function:

#include <iostream>
#include <vector>

void display(std::vector<int>& r_v)
{
std::cout << "vector contents:" << std::endl;

std::vector<int>::iterator it;
for (it = r_v.begin(); it != r_v.end(); it++)
{
std::cout << *it << std::endl;
}
}

int main()
{
std::vector<int> vi;

// add a few elements
vi.push_back(0);
vi.push_back(1);
vi.push_back(2);

std::cout << "vector vi has " << vi.size() << " elements" << std::endl;
display(vi);

// add more elements
vi.push_back(3);
vi.push_back(4);
vi.push_back(5);

std::cout << std::endl << "vector vi has " << vi.size() << " elements"
<< std::endl;
display(vi);

std::cout << std::endl;

return 0;
}
 
D

Darius.Moos AT esigma-systems DOT de

However you can do what you want using the STL containers std::vector or
std::deque, which will grow automatically as you add data to them. They
also have functions to ensure you have enough space to hold a minimum
number of elements. However, one caveat is that each time they grow,
any pointers (or other iterators) into the container become invalid.

Would you elaborate on this a little bit. Does "... become invalid" mean
that the order and offset of the specific elements in the vector could
change and therefor the pointers/iterators become invalid or does it mean
that the order and offset of the vector-elements keep the same when adding
(push_back()) to a vector and just the references become invalid due to
some vector-internal management ?

Thanks in advance for your answer.

Darius.
 
S

Sullivan

It seems that I should spend more time on learning using the classes in
the
C++ library instead of writing from scratch by myself. My work is on
numerical computation so I need to use vector and matrix often. What I did
is to write the classes CVector and CMatrix by myself. Now I know that
vector class may help me much. Thank you.

Try then Newmat library from http://www.robertnz.net/nm_intro.htm
 
J

JKop

Jinjun Xu posted:
Suppose I have an array, e.g., int *p1 = new int[10]; is there any easy
way to reset the length of p1? (e.g, p1 becomes int[20] and the first
10 elements keep the original value).


Imagine that this is your int[10] in memory:


char double int int int int int int int int int int char double int*
unsigned short int


What I'm getting at is that your int[10] may be boxed-in in memory. Thus,
you're *not guaranteed* that you can make it bigger! You'll have to find an
unused bit of memory of length int[20] and move your values.


-JKop
 
P

Prateek R Karandikar

Would you elaborate on this a little bit. Does "... become invalid" mean
that the order and offset of the specific elements in the vector could
change and therefor the pointers/iterators become invalid or does it mean
that the order and offset of the vector-elements keep the same when adding
(push_back()) to a vector and just the references become invalid due to
some vector-internal management ?

When you push_back(), the indices of the existing elements remain the
same, however, the iterators become invalid because the elements might
be moved. Consider reserve().

Thanks in advance for your answer.

You're welcome

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
To iterate is human, to recurse divine.
-L. Peter Deutsch
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
D

Dave Moore

Darius.Moos AT esigma-systems DOT de said:
Would you elaborate on this a little bit. Does "... become invalid" mean
that the order and offset of the specific elements in the vector could
change and therefor the pointers/iterators become invalid or does it mean
that the order and offset of the vector-elements keep the same when adding
(push_back()) to a vector and just the references become invalid due to
some vector-internal management ?

Thanks in advance for your answer.

Well, the terse answer is that they become invalid because the
Standard says so ... I guess the correct way to interpret this is that
the Standard places no restrictions on compiler developers to make
sure that they remain valid, as it does with (for example) std::list.
What that means in the end is that, it doesn't really matter *how*
they become invalid, but rather that you can no longer rely on them to
behave in the correct way.

Sorry if this is a somewhat unsatisfying answer, but I don't really
know the guts of the STL containers, only (some of) what is in the
Standard, which is all that is required for users. There are good
books and websites to help you learn more about implementation details
if you are interested ... try www.accu.org for more info.

As far as your examples are concerned, I think that either of your
suggestions above might be a (partial) answer for a particular
implementation. Note however that if you start relying on a
particular behavior for something that is specified as undefined (or
even implementation-defined), then somewhere down the line your code
is probably going to break.

HTH, Dave Moore
 
O

Old Wolf

JKop said:
Jinjun Xu posted:
Suppose I have an array, e.g., int *p1 = new int[10]; is there any easy
way to reset the length of p1? (e.g, p1 becomes int[20] and the first
10 elements keep the original value).

Imagine that this is your int[10] in memory:

char double int int int int int int int int int int char double int*
unsigned short int

What I'm getting at is that your int[10] may be boxed-in in memory. Thus,
you're *not guaranteed* that you can make it bigger!

You can't make it bigger even if it isn't "boxed in". And this is
silly because memory locations do not have types.
You'll have to find an unused bit of memory of length int[20] and
move your values.

That's what his code did.
 
O

Old Wolf

Darius.Moos AT esigma-systems DOT de said:
Would you elaborate on this a little bit. Does "... become invalid" mean
that the order and offset of the specific elements in the vector could
change and therefor the pointers/iterators become invalid or does it mean
that the order and offset of the vector-elements keep the same when adding
(push_back()) to a vector and just the references become invalid due to
some vector-internal management ?

If you push_back() and the vector has no more memory, it has to
allocate a new block. This could involve getting an entire new block
and copying the data across, rather than resizing the existing block.
Any pointers to the old block would now be indeterminate (so it could
crash your program to use them in any expression). Iterators are often
implemented as pointers, rather than offsets, so the iterators
could now be indeterminate too.
 
S

Siemel Naran

Jinjun Xu said:
Suppose I have an array, e.g., int *p1 = new int[10]; is there any easy way
to reset the length of p1? (e.g, p1 becomes int[20] and the first 10
elements keep the original value).

int var = 0;
std::vector<int*> p(10);
for (int i=0; i<10; i++) p = &var;
p.resize(20);

You can also call reserve(N) to ask the vector to set aside space to
grow to N elements without resizing.

std::vector<int*> p;
p.reserve(30);
p.resize(10);
for (int i=0; i<10; i++) p = &var;
p.resize(20);

You can also use push_back as someone else demonstrated, and reserve
in combination with push_back.

Does anyone know if there are implementations out there for which
p.resize(N) where p is a std::vector<T> where T is a POD type calls
std::realloc(N*sizeof(T))?
 
D

Darius.Moos AT esigma-systems DOT de

If you push_back() and the vector has no more memory, it has to allocate
a new block. This could involve getting an entire new block and copying
the data across, rather than resizing the existing block. Any pointers
to the old block would now be indeterminate (so it could crash your
program to use them in any expression). Iterators are often implemented
as pointers, rather than offsets, so the iterators could now be
indeterminate too.

So do you agree with Prateek R. Karandikar that the indices of vector-
elements do not change by the operation you described ?

Darius.
 
S

SaltPeter

Jinjun Xu said:
Thank you guys for the reply and help! It was my first post in news group
and I am so happy to get the answer quickly and helpfully.

It seems that I should spend more time on learning using the classes in the
C++ library instead of writing from scratch by myself. My work is on
numerical computation so I need to use vector and matrix often. What I did
is to write the classes CVector and CMatrix by myself. Now I know that
vector class may help me much. Thank you.

JJ

Glad to be of help.
Just want to point out that the STL library is not in existance to
discourage the construction of objects or the creation / coding of processes
or procedures. On the contrary, the STL library is a platform-independent,
thoroughly tested set of containers with which to create with.

If what you need is an array, then by all means create an array. You'll find
that a deque, set, bitset, priority_queue or some other STL container might
just fit perfectly to supply the underlying container for an abstract class
(for example).
SaltPeter said:
inline...

Jinjun Xu said:
Hi,

I have an array and I want to adjust the size (remove some elements).
I
use
the following code. Can you help me to check whether it's correct.

////////////// start
int *p1 = new int[oldsize];

// ....
// set the values of p1

int *p2 = p1;
p1 = new int[newsize];

// copy some values from p2 to p1
for ( i = 0; i .... )
if (....) p1 = p2;

delete []p2;

////////////// end

Suppose I have an array, e.g., int *p1 = new int[10]; is there any
easy
way
to reset the length of p1? (e.g, p1 becomes int[20] and the first 10
elements keep the original value).

Thank you very much in advance for your help!

JJ

The easy way is to use a vector instead of an array. Arrays have a fixed
size limitation while a vector container dynamically resizes itself.
Additionally, all STL containers come equipped with powerful member
functions, iterators and algorithms to swap, sort, replace, append, push,
pop, etc...

as a simple example using a vector of integers and a display function:

#include <iostream>
#include <vector>

void display(std::vector<int>& r_v)
{
std::cout << "vector contents:" << std::endl;

std::vector<int>::iterator it;
for (it = r_v.begin(); it != r_v.end(); it++)
{
std::cout << *it << std::endl;
}
}

int main()
{
std::vector<int> vi;

// add a few elements
vi.push_back(0);
vi.push_back(1);
vi.push_back(2);

std::cout << "vector vi has " << vi.size() << " elements" << std::endl;
display(vi);

// add more elements
vi.push_back(3);
vi.push_back(4);
vi.push_back(5);

std::cout << std::endl << "vector vi has " << vi.size() << " elements"
<< std::endl;
display(vi);

std::cout << std::endl;

return 0;
}

 

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
473,780
Messages
2,569,611
Members
45,270
Latest member
TopCryptoTwitterChannels_

Latest Threads

Top