C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

swapping arrays

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
mike
Guest





PostPosted: Fri Jul 16, 2004 12:02 am    Post subject: swapping arrays Reply with 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 {
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





PostPosted: Fri Jul 16, 2004 11:03 am    Post subject: Re: swapping arrays Reply with quote



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





PostPosted: Fri Jul 16, 2004 11:13 am    Post subject: Re: swapping arrays Reply with quote



"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





PostPosted: Fri Jul 16, 2004 11:14 am    Post subject: Re: swapping arrays Reply with quote

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





PostPosted: Fri Jul 16, 2004 11:16 am    Post subject: Re: swapping arrays Reply with quote

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





PostPosted: Fri Jul 16, 2004 11:18 am    Post subject: Re: swapping arrays Reply with quote

[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





PostPosted: Fri Jul 16, 2004 11:20 am    Post subject: Re: swapping arrays Reply with quote

[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





PostPosted: Fri Jul 16, 2004 11:23 am    Post subject: Re: swapping arrays Reply with quote



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





PostPosted: Fri Jul 16, 2004 11:24 am    Post subject: Re: swapping arrays Reply with quote

[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





PostPosted: Sat Jul 17, 2004 10:04 am    Post subject: Re: swapping arrays Reply with quote

[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





PostPosted: Sat Jul 17, 2004 10:04 am    Post subject: Re: swapping arrays Reply with quote

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! Sad 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





PostPosted: Sat Jul 17, 2004 10:17 am    Post subject: Re: swapping arrays Reply with quote

"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





PostPosted: Sun Jul 18, 2004 11:02 am    Post subject: Re: swapping arrays Reply with quote

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:Smile.

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
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
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


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.