new, delete, STL

J

Jon Slaughter

I'm having a problem allocating some elements of a vector then deleting
them.

Basicaly I have something like this:


class base
{
private:
std::vector<object> V;
//std::vector<*object> V;

public:

void addObject()
{
object *temp = new object;
V.push_back(*temp);

//V.push_back(new object);
}


void removeObject(index)
{
delete &V[index];
V.erase(V.begin() + index);

//delete V[index];
//V.erase(V.begin() + index);
}

};

the commented line is where I used the pointerized version. In the first
case the object's destructor gets called twice(I suppose because when I call
addObject the local variable goes out of scope(any way to prevent this) and
in the second case it doesn't get called at all ;/

I'd rather not use a vector of pointers though... I thought maybe I could
declare the object *temp as static but this seems to be kinda a hack... I
just need a way to say "don't call the destructor for this local object when
it goes out of scope" or something.

Any ideas?

Jon
 
C

Cy Edmunds

Jon Slaughter said:
I'm having a problem allocating some elements of a vector then deleting
them.

That's because you are using operator new too much.
Basicaly I have something like this:


class base
{
private:
std::vector<object> V;
//std::vector<*object> V;

public:

void addObject()
{
object *temp = new object;
V.push_back(*temp);

//V.push_back(new object);
}


void removeObject(index)
{
delete &V[index];
V.erase(V.begin() + index);

//delete V[index];
//V.erase(V.begin() + index);
}

};
[snip]

Jon

class base
{
private:
std::vector<object> V;

public:
void addObject()
{
V.push_back(object());
}

void removeObject(index)
{
V.erase(V.begin() + index);
}
};
 
M

Mike Wahler

Jon Slaughter said:
I'm having a problem allocating some elements of a vector then deleting
them.

Really, I find that surprising, since the std::vector
container does all allocations for you automatically.
Basicaly I have something like this:


class base
{
private:
std::vector<object> V;
//std::vector<*object> V;

public:

void addObject()
{
object *temp = new object;
V.push_back(*temp);

Replace previous two lines with:

V.push_back(object());

As I recently wrote in another message, I don't understand
why so many folks feel they need to use 'new' when they really
dont. :)
//V.push_back(new object);
}


void removeObject(index)

This won't compile. You didn't specify the type of the
parameter 'index'. In this case it should be:

void removeObject(std::vector said:
{
delete &V[index];
V.erase(V.begin() + index);

//delete V[index];
//V.erase(V.begin() + index);

Replace all that with:

if(!V.empty()) // to prevent possible UB
V.erase(V.begin() + index);
}

};

the commented line is where I used the pointerized version. In the first
case the object's destructor gets called twice(I suppose because when I
call addObject the local variable goes out of scope(any way to prevent
this) and in the second case it doesn't get called at all ;/

I'd rather not use a vector of pointers though... I thought maybe I could
declare the object *temp as static but this seems to be kinda a hack... I
just need a way to say "don't call the destructor for this local object
when it goes out of scope" or something.

No, don't try to circumvent the way the language works, better
to understand it and use it in the intended ways.

-Mike
 
M

Mike Wahler

Pete Becker said:
if (!V.empty() && index < V.size())

But only if the specification calls for it.

My mind is going, Dave... I can feeel it .... :)

Note to self: Test, Test, Test. :)

Thanks, Pete.

-Mike
 
R

red floyd

Mike said:
As I recently wrote in another message, I don't understand
why so many folks feel they need to use 'new' when they really
dont. :)

Coming from Java or VB? When I code Java, I have the reverse problem,
coming from C++, I tend *not* to use new enough.
 
R

red floyd

red said:
Clarification:

Coming from Java or VB? When I code Java, I have the reverse problem,
coming from C++, I tend *not* to use new enough.

I meant, "maybe they are coming from Java or VB".
 
J

Jon Slaughter

Ok then, can some one explain what is going on here then? this is
contradictory to what you guys have said to do to get it to work(cause it
doesn't):

The output is

Object being created
Object being removed
Object being removed
Object being removed

I don't understand how the destructor can be called 3 times and the
constructor called only once(so there should be only one instance of the
object and after the first call of the destructor the instance should be
gone and no more destructor to call).
#include "stdafx.h"

#include <vector>

#include <iostream>



class object

{

public:

object()

{

std::cout << "Object being created\n";

};

~object()

{

std::cout << "Object being removed\n";

};

};

class test

{

private:

std::vector<object> Objects;

public:

test(){ };

void Add()

{

Objects.push_back(object()); // outputs 3 lines Object being created \n
Object being removed \n Object being removed \n

};

void Remove()

{

Objects.erase(Objects.begin()); // outputs one line Object being removed

};

~test() {};

};





int main(int argc, _TCHAR* argv[])

{

test Test;

Test.Add();

Test.Remove();

return 0;

}
 
J

Jon Slaughter

// test1.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <vector>
#include <iostream>

class object
{
public:
object()
{
std::cout << "Object being created\n";
};
~object()
{
std::cout << "Object being removed\n";
};
};
class test
{
private:
std::vector<object> Objects;
public:
test(){ };
void Add()
{
static object *o = new object; // prints "object being created"
Objects.insert(Objects.begin(), 1, *o); // prints "object being removed"
// Objects.push_back(*o); // same

// same problem if one doesn't use the static pointer method i.e.
Objects.push_Back(object()); does exact same thing

};
void Remove()
{
Objects.erase(Objects.begin());
// crashes debugger
};
~test() {};
};


int main(int argc, _TCHAR* argv[])
{
//object *o = new object;
//delete o;
// code above works exactly as its suppose to


test Test;


Test.Add();
Test.Remove();

return 0;
}


Any ideas?
 
M

Mike Wahler

Jon Slaughter said:
Ok then, can some one explain what is going on here then? this is
contradictory to what you guys have said to do to get it to work(cause it
doesn't):

Yes, it does work. Why do you think it doesn't?
The output is

Object being created
Object being removed
Object being removed
Object being removed

This is only the output you told the program to give
(but there are other things happening which you did
not intercept with your 'cout' statements.)

However (after removing the nonstandard stuff and a syntax error)
after compiling your code, I get output of:

Object being created
Object being removed
Object being removed

Which is what I'd expect.
I don't understand how the destructor can be called 3 times and the
constructor called only once(so there should be only one instance of the
object and after the first call of the destructor the instance should be
gone and no more destructor to call).

Despite what your output says, an 'object' constructor is being
called twice, and a destructor twice. What you're missing is
that it isn't the *default* constructor getting called twice --
one call is to the default constructor, and the other is to the
copy constructor (since you didn't define one,the compiler synthesized
one for you).

Read about the standard containers' 'copy semantics'.

(After reading my notes embedded in your code, see my
example which follows your code.)
#include "stdafx.h"

No such header in standard C++, and you don't need it to
demonstrate your problem.
#include <vector>

#include <iostream>



class object

{

public:

object()

{

std::cout << "Object being created\n";

};

You don't need a semicolon after the closing brace of a function.
Only after a class definition's closing brace.
~object()

{

std::cout << "Object being removed\n";

};

};

class test

{

private:

std::vector<object> Objects;

public:

test(){ };

You don't need this constructor.
void Add()

{

Objects.push_back(object()); // outputs 3 lines Object being created \n
Object being removed \n Object being removed \n

};

void Remove()

{

Objects.erase(Objects.begin()); // outputs one line Object being removed

};

~test() {};

You don't need this destructor.
};

int main(int argc, _TCHAR* argv[])

There's no such type as _TCHAR in standard C++. ANd your
program does not use command-line arguments anyway.

And please indent your code, otherwise it's rather hard to follow.
{

test Test;

Test.Add();

Test.Remove();

return 0;

}

#include <vector>
#include <iostream>

class object
{
public:
object() { std::cout << "Object being created\n"; }
object(const object&) { std::cout << "Object being created\n"; }
~object() { std::cout << "Object being removed\n"; }
};

class test
{
private:
std::vector<object> Objects;
public:
void Add() { Objects.push_back(object()); }
void Remove() { Objects.erase(Objects.begin()); }
};

int main()
{
test Test;
Test.Add();
Test.Remove();
return 0;
}

Output:

Object being created
Object being created
Object being removed
Object being removed

The first 'created' message refers to the default ctor
getting called for the temporary object which is created
by the expression 'object()' in the statement:

Objects.push_back(object());

The second 'created' message refers to the copy ctor
getting called when the 'push_back()' function makes
a copy of your object to store in the vector.

The first 'removed' message refers to the destructor
getting called when the temporary object (created by
'push_back()' gets destroyed.

The second 'removed' message refers to the destructor
getting called when 'Test.Remove()' calls 'vector::erase()'.

-Mike
 
M

Mike Wahler

Jon Slaughter said:
// test1.cpp : Defines the entry point for the console application.
//

[snip (an attempt to use operator 'new' to fix a 'problem'
to which it is completely unrelated.) ]
Any ideas?

Yes. Stop guessing and read a good C++ text. (See my
other post this thread for explanation of your specific
example's behavior.)

-Mike
 
J

Jon Slaughter

Mike Wahler said:
Jon Slaughter said:
// test1.cpp : Defines the entry point for the console application.
//

[snip (an attempt to use operator 'new' to fix a 'problem'
to which it is completely unrelated.) ]
Any ideas?

Yes. Stop guessing and read a good C++ text. (See my
other post this thread for explanation of your specific
example's behavior.)

-Mike

You know... you are pretty arrogant... if you get so worked up over helping
then why do it? I didn't ask for your specific help and if you are going to
be an asshole about it then don't offer it.
 
J

Jon Slaughter

Mike Wahler said:
Yes, it does work. Why do you think it doesn't?

Nope, doesn't work.. sorry.. an object's destructor should be only called
once and no more than once. If STL is copying the object and destorying the
first copy then thats all you had to say...
This is only the output you told the program to give
(but there are other things happening which you did
not intercept with your 'cout' statements.)

However (after removing the nonstandard stuff and a syntax error)
after compiling your code, I get output of:

there was no syntax error... it compiled for me perfectly and I copied the
code directly.
Object being created
Object being removed
Object being removed

Which is what I'd expect.

Hmm. being removed twice? you expect that?
Despite what your output says, an 'object' constructor is being
called twice, and a destructor twice. What you're missing is
that it isn't the *default* constructor getting called twice --
one call is to the default constructor, and the other is to the
copy constructor (since you didn't define one,the compiler synthesized
one for you).

ok, thats all you had to say in the first place.. .very simple. I don't know
much about STL and copy constructors in the first place and all you had to
do was mention that and there would have been no problems. Now that I know
that STL is copying the objects I prefer not to use it. Its a waste of time
for it to copy them in my situation.
Read about the standard containers' 'copy semantics'.
(After reading my notes embedded in your code, see my
example which follows your code.)


No such header in standard C++, and you don't need it to
demonstrate your problem.

Um.. jesus christ.. who cares then? you must hate people that use XP and VS
then because just about every post you have been an ass about stuff like
this(first off the OP was just more like psuedo code and not ment to compile
but to get my problem across)
You don't need a semicolon after the closing brace of a function.
Only after a class definition's closing brace.

UM, it doesnt' freaken matter if you put it there or not... so why bother?
stop being an ass.
You don't need this constructor.

SO? doesn't hurt anything either. stop being an ass.
void Add()

{

Objects.push_back(object()); // outputs 3 lines Object being created \n
Object being removed \n Object being removed \n

};

void Remove()

{

Objects.erase(Objects.begin()); // outputs one line Object being removed

};

~test() {};

You don't need this destructor.
ass!
};

int main(int argc, _TCHAR* argv[])

There's no such type as _TCHAR in standard C++. ANd your
program does not use command-line arguments anyway.

And please indent your code, otherwise it's rather hard to follow.

My code is perfectly indented but when I copyed it over the formatting got
left behind(Because I first had to convert it to rich text then back to
plain text because thef irst insertion copied all the formatting and special
character and double spacing crap that made it hard to follow(even though I
know it was going to turn into normal plain text when I posted it))
#include <vector>
#include <iostream>

class object
{
public:
object() { std::cout << "Object being created\n"; }
object(const object&) { std::cout << "Object being created\n"; }
~object() { std::cout << "Object being removed\n"; }
};

class test
{
private:
std::vector<object> Objects;
public:
void Add() { Objects.push_back(object()); }
void Remove() { Objects.erase(Objects.begin()); }
};

int main()
{
test Test;
Test.Add();
Test.Remove();
return 0;
}

Output:

Object being created
Object being created
Object being removed
Object being removed

The first 'created' message refers to the default ctor
getting called for the temporary object which is created
by the expression 'object()' in the statement:

Yes, I see that now and if you would have said that in the first place we
could have saved each other a lot more time... all you had to do was mention
that STL copies the object to a new one in its container and I would have
completely understood... but you assume I am a complete idiot and have no
idea about anything.
Objects.push_back(object());

The second 'created' message refers to the copy ctor
getting called when the 'push_back()' function makes
a copy of your object to store in the vector.

The first 'removed' message refers to the destructor
getting called when the temporary object (created by
'push_back()' gets destroyed.

The second 'removed' message refers to the destructor
getting called when 'Test.Remove()' calls 'vector::erase()'.

-Mike

Well, for future reference why don't you just not reply to my messages?
Just because you think your the god of programming doesn't mean you have to
treat others like idiots.
 
J

Jon Slaughter

#include <vector>
#include <iostream>

class object
{
public:
object() { std::cout << "Object being created\n"; }
object(const object&) { std::cout << "Object being created\n"; }
~object() { std::cout << "Object being removed\n"; }
};

class test
{
private:
std::vector<object> Objects;
public:
void Add() { Objects.push_back(object()); }
void Remove() { Objects.erase(Objects.begin()); }
};

int main()
{
test Test;
Test.Add();
Test.Remove();
return 0;
}

Output:

Object being created
Object being created
Object being removed
Object being removed


BTW, copying and pasting your code directly gives the output of(I did not
change a damn thing either).

Object being created
Object being created
Object being created
Object being removed
Object being removed
Object being removed
 
J

Jon Slaughter

After changing your code to


// test1.cpp : Defines the entry point for the console application.

//

#include <vector>

#include <iostream>

class object

{

public:

object() { std::cout << "Object being created\n"; }

object(const object&) { std::cout << "Object being copied\n"; }

~object() { std::cout << "Object being removed\n"; }

};

class test

{

private:

std::vector<object> Objects;

public:

void Add() { Objects.push_back(object()); }

void Remove() { Objects.erase(Objects.begin()); }

};

int main()

{

test Test;

Test.Add();

Test.Remove();

return 0;

}







the output is



Object being created
Object being copied
Object being copied
Object being removed
Object being removed
Object being removed




Hell if I know why that one line of code causes the object to be copied
twice... and I doubt I'll find the answer in the shity STL documents you
refer to.
 
J

Jon Slaughter

To be even more clear:

// test1.cpp : Defines the entry point for the console application.

//

#include <vector>

#include <iostream>

class object

{

public:

object() { std::cout << "Object being created\n"; }

object(const object&) { std::cout << "Object being copied\n"; }

~object() { std::cout << "Object being removed\n"; }

};

class test

{

private:

std::vector<object> Objects;

public:

void Add() { std::cout << "Test.Add() {\n";

Objects.push_back(object()); std::cout << "Test.Add() }\n"; }

void Remove() { std::cout << "Test.Remove() {\n";

Objects.erase(Objects.begin()); std::cout << "Test.Remove() }\n"; }

};

int main()

{

test Test;

Test.Add();

Test.Remove();

return 0;

}



gives an output of



Test.Add() {
Object being created
Object being copied
Object being copied
Object being removed
Object being removed
Test.Add() }
Test.Remove() {
Object being removed
Test.Remove() }




So there are several problems with this... first its a waste of time and
resource(even though it is freed almost immediately) to create an empty
instance of an object just so it can be immediately copied then freed.
Second, atleast in my case, it is copying the damn thing twice and if the
object happens to be very large then this could be a huge waste. Maybe I
will try this with gcc and see what I get. While I can possibly live with
one extraneous copy I can't/won't live with two.
 
P

persenaama

The explanation is probably very simple. std::vector is basicly
mimicking array semantics for memory storage, looks like a duck, sounds
like a duck.. walks like a duck, anyway..

When vector runs out of capacity, it is grown.. when vector is grown
new objects are being created, and existing ones are *copied* to the
new storage that is being allocated. It is not defined as far as I can
remember how large the capacity of a vector is initially, and I don't
remember liking to read Dinkumware's (whose implementation you are
currently using) code very much (sorry DW).

The small vectors rarely can both, efficient in runtime and memory
footprint. If they are runtime efficient then it means they need some
larger constant as initial capacity, which wastes memory and
vice-versa. In this context, how would you implement your Standard
Library's vector class? ;-)

So all in all, this comes down to design tradeoffs by your Standard
Library vendor.. if you make the vector larger, with more objects, you
might observe more efficiency taking place immediately.

Btw. Just out of morbid curiosity, if your vector overflows.. which is
better, to double the size, or grow only 50%, or if something else,
what? I know the Dinkumware's (old) answer to this because this was
covered, I think in this same group some years ago, I recall P.Becker
(?) mentioned some rationale to explain the behaviour. I'm drifting
off-topic for your concerns but just popped to mind..

I hope this was any help..
 
K

Karl Heinz Buchegger

Jon said:
Yes, I see that now and if you would have said that in the first place we
could have saved each other a lot more time...

Everyone would have saved 'a lot more time' if you just would swallow down
your pride and *read* a book about C++.

What you are dealing with here is all pretty basic C++.
 

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

Forum statistics

Threads
474,001
Messages
2,570,254
Members
46,849
Latest member
Fira

Latest Threads

Top