1

in an answer to this question I have been informed that my problems lie to the call to a copy constructor in the code below. However, I just don't see where it's being invoked. Nowhere am I doing something like agents[1] = agents[0]; although clearly I don't understand something. Where is this copying occurring and how can I change it so it's just making new objects each time?

I have been

int main()
{
    Level* level;
    std::vector<Agent> agents;

    level = new Level(agents);

    for (int i = 0; i < 1; i++) // this will be more than 1 in the future.
    {
        agents.push_back(Agent(100, *level, agents, level->Pickups(), D3DXCOLOR(1.0F, 0.4f, 0.4f, 1.0f)));
    }

    delete level;

}
Community
  • 1
  • 1
Dollarslice
  • 9,917
  • 22
  • 59
  • 87
  • I suppose that you use a pointer to Level only for an example on stackoverflow, and not in real code where an object would be more appropriate? – Tristram Gräbener Dec 06 '11 at 12:29
  • @TristramGräbener: If `Level` is really really huge, it might not only be heaped for StackOverflow (the site) but to prevent stack-overflows (the error). – bitmask Dec 06 '11 at 12:35
  • It's rather difficult to have really huge objects (excepted using arrays, what i'd discourage in favor of vectors). And he dereferences level to pass it to the constructor of Agent, so I'm not convinced its size is a real problem (of course, it might be passed as reference... who knows) – Tristram Gräbener Dec 06 '11 at 13:00
  • I don't understand, what's the problem with creating a new level and using a pointer to refer to it? – Dollarslice Dec 06 '11 at 13:30

4 Answers4

6

As others have said, push_back will insert a copy into the vector.

If you have a compiler with some C++11 support it's possibly that you can avoid this copy by constructing the object directly into the vector. The new emplace_back function does this:

agents.emplace_back(100, *level, agents, level->Pickups(), D3DXCOLOR(1.0F, 0.4f, 0.4f, 1.0f));

In addition, if the compiler has C++11 support for move semantics, push_back will do a move operation instead of a copy operation if a move constructor is available for Agent, because you're passing it a temporary.

R. Martinho Fernandes
  • 228,013
  • 71
  • 433
  • 510
  • 1
    the missing `Agent` before the parameters is deliberate? – Dollarslice Dec 06 '11 at 12:35
  • @SirYakalot Yes, `emplace_back` takes the constructor parameters and calls the constructor itself. – R. Martinho Fernandes Dec 06 '11 at 12:36
  • 1
    One question - push_back creates an object and copies it in to the vector, but how long does the original object persist for? until the loop ends? or every time it loops? – Dollarslice Dec 06 '11 at 12:53
  • also I just changed my code to this, and I get "too many arguments in function call". It seems to want me to put `Agent` before the arguments. – Dollarslice Dec 06 '11 at 12:56
  • 1
    @SirYakalot the original object lasts until the end of the statement. It goes away immediately after the function call. And it's not `push_back` that creates the original object, it's the `Agent(..)` part. `push_back` just copies that. Now, what compiler are you using? It may be that `emplace_back` is not supported by it yet. – R. Martinho Fernandes Dec 06 '11 at 13:01
  • I just checked, and if you're using Microsoft's compiler, `emplace_back` is not correctly supported (more here: http://stackoverflow.com/a/4306581/46642). – R. Martinho Fernandes Dec 06 '11 at 13:13
  • visual studio 2010, it's OK i'm reading up about copy constructors to solve my other problem. Thanks for your help though! – Dollarslice Dec 06 '11 at 13:31
2

Here:

agents.push_back(Agent(100, *level, agents, level->Pickups(), D3DXCOLOR(1.0F, 0.4f, 0.4f, 1.0f)));

This creates a temporary Agent object and a copy of it is taken an pushed in the vector.

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
0

at the line below you are creating a temporary Agent and copying it into a new Agent that is created within the agents by passing the temporary Agent.

agents.push_back(Agent(100, *level, agents, level->Pickups(), D3DXCOLOR(1.0F, 0.4f, 0.4f, 1.0f)));

perreal
  • 94,503
  • 21
  • 155
  • 181
0

Your std::vector::push_back has copy semantics. It must invoke Agent::Agent(Agent const&).

You cannot use std::vector with something that does not have a meaningful copy constructor. You might have to resort to a vector of pointers (which have trivial copy constructors).

bitmask
  • 32,434
  • 14
  • 99
  • 159
  • what exactly is `Agent::Agent(Agent const&)`? – Dollarslice Dec 06 '11 at 12:30
  • @SirYakalot: `Agent::Agent(Agent const&)` is the prototype of the copy constructor of the `Agent` type. – bitmask Dec 06 '11 at 12:32
  • so is my problem that I AM using it? or that I'm not? Sorry I don't quite understand. – Dollarslice Dec 06 '11 at 12:34
  • @SirYakalot: I can only guess, because your question is a bit vague. I would assume that you asked because your compiler told you that there is no copy constructor. `std::vector` requires one (**it** uses it) and if you implemented at least one constructor but didn't explicitly implement the copy constructor, the default copy constructor was removed by C++, resulting in a type that lacks the ability to be copy constructed, hence lacks the ability to be stored in `std::vector`. – bitmask Dec 06 '11 at 12:38
  • @bitmask: the copy constructor is not removed if you implement another constructor (the default constructor is, though). – R. Martinho Fernandes Dec 06 '11 at 12:43
  • @R.MartinhoFernandes: Ah, darn. You're right -- you have to explicitly hide it if you don't want it. Sorry for the mix up. – bitmask Dec 06 '11 at 12:46