 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
mike Guest
|
Posted: Fri Jul 16, 2004 12:02 am Post subject: swapping arrays |
|
|
Hi
I have a class that contains a pointer to a large array as one of its
members - so a stripping down version could just be
class myclass
{
private:
int size; //size of the data array
double *data;
public:
//various member functions that I don't need to mention including
constructors and destructors
void calculate();
};
Now the myclass::calculate() function performs some operation on the
array and REPLACES the original array with the results of the
calculation. The particulars of the calculation are such that I
cannot replace the original array as I go but I have to create a
temporary results array - in summary....
void myclass::calculate();
{
double *results = new double[size];
//perform calculation here
//now put the results array into the data array
for(int count = 0; count
{
data[count] = results[count];
}
delete [] results;
}
My question is - do I need that last for loop? Ideally I would like
to just change the data pointer so it points to the results and then
delete the original data but whatever I try seems like it may cause
problems:
data = results; //data now points to results array but how can I
delete the original data array
I apologise if I am being stupid - any help would be appreciated
Mike
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Ali Cehreli Guest
|
Posted: Fri Jul 16, 2004 11:03 am Post subject: Re: swapping arrays |
|
|
On Thu, 15 Jul 2004 17:02:04 -0700, mike wrote:
| Quote: | I have a class that contains a pointer to a large array as one of its
members - so a stripping down version could just be
class myclass
{
private:
int size; //size of the data array
double *data;
public:
//various member functions that I don't need to mention including
constructors and destructors
void calculate();
};
Now the myclass::calculate() function performs some operation on the
array and REPLACES the original array with the results of the
calculation. The particulars of the calculation are such that I cannot
replace the original array as I go but I have to create a temporary
results array - in summary....
void myclass::calculate();
{
double *results = new double[size];
//perform calculation here
//now put the results array into the data array
for(int count = 0; count<size*2; count++) {
data[count] = results[count];
}
delete [] results;
}
My question is - do I need that last for loop? Ideally I would like to
just change the data pointer so it points to the results and then delete
the original data but whatever I try seems like it may cause problems:
data = results; //data now points to results array but how can I
delete the original data array
|
Why not delete the original data first?
delete [] data;
data = results;
And why not use std::vector instead of size and data, which would make
your class easier to maintain and /more/ exception-safe:
class myclass
{
std::vector
/* ... */
};
void myclass::calculate()
{
std::vector<double> results;
results.resize(data.size()); // for efficiency; optional
// 'size' number of results.push_back(/* ... */) calls
// in the end, efficient and exception-safe swapping
data.swap(results);
/*
old data is deleted automatically at this point
when results goes out of scope
*/
}
Ali
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Ivan Vecerina Guest
|
Posted: Fri Jul 16, 2004 11:13 am Post subject: Re: swapping arrays |
|
|
"mike" <mike_uk31415 (AT) yahoo (DOT) co.uk> wrote
| Quote: | I have a class that contains a pointer to a large array as one of its
members - so a stripping down version could just be
class myclass
{
private:
int size; //size of the data array
double *data;
....
void myclass::calculate();
{
double *results = new double[size];
//perform calculation here
|
Note that if any code here throws an exception, a memory
leak will occur (because results will not be deleted).
| Quote: | //now put the results array into the data array
for(int count = 0; count<size*2; count++)
count
{
data[count] = results[count];
}
delete [] results;
}
My question is - do I need that last for loop?
No. |
You can safely replace the loop and final line with:
delete[] results;
results = data;
This is safe because delete[] will never throw an exception.
But what you really should be doing is use an std::vector:
First:
#include
Then replace the data members with:
std::vector<double> data;
The vector can be used pretty much like an array,
but will delete its contents automatically when out of scope.
You can use data.size() to get the current item count,
and data.resize(newSize) to change the size of the array.
Finally, the calculate() member function would become:
void myclass::calculate();
{
std::vector<double> results(data.size()); // allocates 'size' items
//perform calculation here
//now put the results array into the data array
results.swap( data ); // exchange data with results,
//... old data will automatically be deleted here
}
This code is exception safe, less error-prone, and more concise...
hth,
Ivan
--
http://ivan.vecerina.com/contact/?subject=NG_POST <- e-mail contact form
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Jozef Saniga Guest
|
Posted: Fri Jul 16, 2004 11:14 am Post subject: Re: swapping arrays |
|
|
Hi,
mike wrote:
| Quote: | Hi
snip
Now the myclass::calculate() function performs some operation on the
array and REPLACES the original array with the results of the
calculation. The particulars of the calculation are such that I
cannot replace the original array as I go but I have to create a
temporary results array - in summary....
void myclass::calculate();
{
double *results = new double[size];
//perform calculation here
//now put the results array into the data array
for(int count = 0; count
The loop accesses elements 0 through 2*size but your arrays have only |
size elements each.
| Quote: | {
data[count] = results[count];
}
delete [] results;
}
My question is - do I need that last for loop? Ideally I would like
to just change the data pointer so it points to the results and then
delete the original data but whatever I try seems like it may cause
problems:
data = results; //data now points to results array but how can I
delete the original data array
delete [] data; |
data = results;
or
double* tmp = data;
data = results;
delete [] tmp;
| Quote: |
I apologise if I am being stupid - any help would be appreciated
Mike
|
Jozef
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Daniel Krügler (ne Spange Guest
|
Posted: Fri Jul 16, 2004 11:16 am Post subject: Re: swapping arrays |
|
|
Good Morning Mike,
mike schrieb:
| Quote: | Hi
I have a class that contains a pointer to a large array as one of its
members - so a stripping down version could just be
class myclass
{
private:
int size; //size of the data array
double *data;
public:
//various member functions that I don't need to mention including
constructors and destructors
void calculate();
};
Now the myclass::calculate() function performs some operation on the
array and REPLACES the original array with the results of the
calculation. The particulars of the calculation are such that I
cannot replace the original array as I go but I have to create a
temporary results array - in summary....
void myclass::calculate();
{
double *results = new double[size];
//perform calculation here
//now put the results array into the data array
for(int count = 0; count<size*2; count++)
As far as I see, you do make an index error here due to the index range |
[0..2*size). Note that
you actually don't need this elementwise assignment. I'll give you an
alternative to your implementation
below. If you insist on that assigment, use either
for(int count = 0; count
data[count] = results[count];
}
or alternatively after #include'ing
std::copy(&results[0], &results[size], &data[0]);
| Quote: | {
data[count] = results[count];
}
delete [] results;
}
My question is - do I need that last for loop? Ideally I would like
to just change the data pointer so it points to the results and then
delete the original data but whatever I try seems like it may cause
problems:
data = results; //data now points to results array but how can I
delete the original data array
You really don't need the loop, just use std::swap: |
void myclass::calculate()
{
double *results = new double[size];
//perform calculation here
//now swap the results array and data array
std::swap(results, data);
// Now results points onto the original address of data and vice versa.
// So deleteing results will effectivly delete the original data memory
// area:
delete [] results;
}
After providing this possible solution, lets discuss its consequences
The bad news are: Neither the
original nor the modified implementation of myclass::calculate() are
exception-save. Both don't fulfil
the basic guarantee in case of your implied "calculation" after memory
allocation, which would result
in a memory leak. You should be strongly aware of that possibility,
especially if you invoke an
externally defined callback function here. So you might consider to
replace your raw double* data
member by std::vector<double> or a similar array wrapper (e.g. from boost).
Hope that helps,
Daniel Krügler
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Joshua Lehrer Guest
|
Posted: Fri Jul 16, 2004 11:18 am Post subject: Re: swapping arrays |
|
|
[email]mike_uk31415 (AT) yahoo (DOT) co.uk[/email] (mike) wrote in message news:<8ccca585.0407150527.50685904 (AT) posting (DOT) google.com>...
| Quote: | void myclass::calculate();
{
double *results = new double[size];
//perform calculation here
//now put the results array into the data array
for(int count = 0; count<size*2; count++)
{
data[count] = results[count];
}
delete [] results;
}
My question is - do I need that last for loop? Ideally I would like
to just change the data pointer so it points to the results and then
delete the original data but whatever I try seems like it may cause
problems:
|
Your inclination is correct for more reasons than one.
Usually, when you write "correct" code, you can solve lots of problems
without even realising it.
The code above is not exception safe. If something goes wrong during
the calculation, you will leak the memory allocated to results.
The code above is inefficient, due to that extra copy loop.
To solve these problems, use smart pointers instead:
struct myclass {
boost::scoped_array
void calculate();
};
void myclass::calculate() {
boost::scoped_array<double> results(new double[size]);
//perform calculation
results.swap(data);
}
results.swap(data) exchanges the pointers between the temporary
"results" and the data memory "data". Now, "results" holds the old
data, and "data" holds the new results. At the close of the scope of
"calculate", "results" is destroyed, freeing the original
pre-calculation data.
joshua lehrer
factset research systems
NYSE:FDS
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Joshua Lehrer Guest
|
Posted: Fri Jul 16, 2004 11:20 am Post subject: Re: swapping arrays |
|
|
[email]mike_uk31415 (AT) yahoo (DOT) co.uk[/email] (mike) wrote in message news:<8ccca585.0407150527.50685904 (AT) posting (DOT) google.com>...
| Quote: | void myclass::calculate();
{
double *results = new double[size];
//perform calculation here
//now put the results array into the data array
for(int count = 0; count<size*2; count++)
{
data[count] = results[count];
}
delete [] results;
}
My question is - do I need that last for loop? Ideally I would like
to just change the data pointer so it points to the results and then
delete the original data but whatever I try seems like it may cause
problems:
|
Your inclination is correct for more reasons than one.
Usually, when you write "correct" code, you can solve lots of problems
without even realising it.
The code above is not exception safe. If something goes wrong during
the calculation, you will leak the memory allocated to results.
The code above is inefficient, due to that extra copy loop.
To solve these problems, use smart pointers instead:
struct myclass {
boost::scoped_array
void calculate();
};
void myclass::calculate() {
boost::scoped_array<double> results(new double[size]);
//perform calculation
results.swap(data);
}
results.swap(data) exchanges the pointers between the temporary
"results" and the data memory "data". Now, "results" holds the old
data, and "data" holds the new results. At the close of the scope of
"calculate", "results" is destroyed, freeing the original
pre-calculation data.
joshua lehrer
factset research systems
NYSE:FDS
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Wouter Genuit Guest
|
Posted: Fri Jul 16, 2004 11:23 am Post subject: Re: swapping arrays |
|
|
| Quote: | void myclass::calculate();
{
double *results = new double[size];
//perform calculation here
//now put the results array into the data array
for(int count = 0; count
{
data[count] = results[count];
}
This will corrupt your memory, since your array its length is just size and |
you are looping from 0 to 2*size
| Quote: |
delete [] results;
}
My question is - do I need that last for loop? Ideally I would like
to just change the data pointer so it points to the results and then
delete the original data but whatever I try seems like it may cause
problems:
data = results; //data now points to results array but how can I
delete the original data array
|
delete[] data;
data == results;
Wouter
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Michiel Salters Guest
|
Posted: Fri Jul 16, 2004 11:24 am Post subject: Re: swapping arrays |
|
|
[email]mike_uk31415 (AT) yahoo (DOT) co.uk[/email] (mike) wrote in message news:<8ccca585.0407150527.50685904 (AT) posting (DOT) google.com>...
| Quote: | Hi
I have a class that contains a pointer to a large array as one of its
members - so a stripping down version could just be
class myclass
{
private:
int size; //size of the data array
double *data;
public:
//various member functions that I don't need to mention including
constructors and destructors
void calculate();
};
|
It would be easier if you had a std::vector<double> data;
| Quote: | Now the myclass::calculate() function performs some operation on the
array and REPLACES the original array with the results of the
calculation. The particulars of the calculation are such that I
cannot replace the original array as I go but I have to create a
temporary results array - in summary....
void myclass::calculate();
{
double *results = new double[size];
//perform calculation here
//now put the results array into the data array
for(int count = 0; count<size*2; count++)
{
data[count] = results[count];
}
delete [] results;
}
My question is - do I need that last for loop?
|
No:
std::swap( this->data, results );
delete[] results; // what used to be in this->data
Of course, this->data must be initialized with the result
of new[] as well (malloc or plain new are unacceptable),
but since it's a class member, you control that. Don't forget
copy ctors and the dtor, and assignment is tricky too.
Or switch to std::vector and have the compiler sort it out.
Vectors can be swapped efficiently as well.
Regards,
Michiel Salters
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Joshua Lehrer Guest
|
Posted: Sat Jul 17, 2004 10:04 am Post subject: Re: swapping arrays |
|
|
[email]mike_uk31415 (AT) yahoo (DOT) co.uk[/email] (mike) wrote in message news:<8ccca585.0407150527.50685904 (AT) posting (DOT) google.com>...
| Quote: | void myclass::calculate();
{
double *results = new double[size];
//perform calculation here
//now put the results array into the data array
for(int count = 0; count<size*2; count++)
{
data[count] = results[count];
}
delete [] results;
}
My question is - do I need that last for loop? Ideally I would like
to just change the data pointer so it points to the results and then
delete the original data but whatever I try seems like it may cause
problems:
|
Your inclination is correct for more reasons than one.
Usually, when you write "correct" code, you can solve lots of problems
without even realising it.
The code above is not exception safe. If something goes wrong during
the calculation, you will leak the memory allocated to results.
The code above is inefficient, due to that extra copy loop.
To solve these problems, use smart pointers instead:
struct myclass {
boost::scoped_array
void calculate();
};
void myclass::calculate() {
boost::scoped_array<double> results(new double[size]);
//perform calculation
results.swap(data);
}
results.swap(data) exchanges the pointers between the temporary
"results" and the data memory "data". Now, "results" holds the old
data, and "data" holds the new results. At the close of the scope of
"calculate", "results" is destroyed, freeing the original
pre-calculation data.
joshua lehrer
factset research systems
NYSE:FDS
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Ali Cehreli Guest
|
Posted: Sat Jul 17, 2004 10:04 am Post subject: Re: swapping arrays |
|
|
On Fri, 16 Jul 2004 07:03:10 -0400, Ali Cehreli wrote:
| Quote: | std::vector<double> results;
results.resize(data.size()); // for efficiency; optional
|
That common bug again! I meant
results.reserve(data.size());
Two functions with close enough semantics and they have three common
first letters :)
resize: Change the size of the vector; the member count is now data.size()
reserve: Reserve memory for the vector; it is still empty
Ali
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
mike Guest
|
Posted: Sat Jul 17, 2004 10:17 am Post subject: Re: swapping arrays |
|
|
"Daniel Krügler (ne Spangenberg)" <dsp (AT) bdal (DOT) de> wrote
| Quote: | Good Morning Mike,
You really don't need the loop, just use std::swap:
void myclass::calculate()
{
double *results = new double[size];
//perform calculation here
//now swap the results array and data array
std::swap(results, data);
// Now results points onto the original address of data and vice versa.
// So deleteing results will effectivly delete the original data memory
// area:
delete [] results;
}
After providing this possible solution, lets discuss its consequences
The bad news are: Neither the
original nor the modified implementation of myclass::calculate() are
exception-save. Both don't fulfil
the basic guarantee in case of your implied "calculation" after memory
allocation, which would result
in a memory leak. You should be strongly aware of that possibility,
especially if you invoke an
externally defined callback function here. So you might consider to
replace your raw double* data
member by std::vector<double> or a similar array wrapper (e.g. from boost).
Hope that helps,
Daniel Krügler
|
Thanks for the advice Daniel - its much appreciated. I have never
come across the std::swap function before. I would be perfectly happy
to change to vectors since I have used them many times before. I was
wondering about using the C-style array because I have a lot of data
to consider and performance is a big issue to me. Does anyone know
how much (if any) overhead is incurred in using a vector rather than a
C-style array?
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Sebastian Kapfer Guest
|
Posted: Sun Jul 18, 2004 11:02 am Post subject: Re: swapping arrays |
|
|
On Sat, 17 Jul 2004 06:17:36 -0400, mike wrote:
| Quote: | I was
wondering about using the C-style array because I have a lot of data to
consider and performance is a big issue to me. Does anyone know how
much (if any) overhead is incurred in using a vector rather than a
C-style array?
|
It depends on your specific program. Most of the time, std::vector is
just fine (that's why it is in std: .
You might want to do a little research on the topic of "premature
optimization". In short, use std::vector whenever you need an resizable
array. If you're having performance problems (that is, your _finished_
program spends too much time working with vectors, i.e. the overhead is
measurable), you can still choose a better implementation later on.
--
Best Regards, | This signature intentionally left blank.
Sebastian |--------------------------------------------------------
| Quote: | mailbox in "From" silently drops any mail > 20k
|
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|