Returning automatic local objects in C++ - c++

I'm trying to understand some aspects of C++.
I have written this short programme to show different ways of returning objects from functions in C++:
#include <iostream>
using namespace std;
// A simple class with only one private member.
class Car{
private:
int maxSpeed;
public:
Car( int );
void print();
Car& operator= (const Car &);
Car(const Car &);
};
// Constructor
Car::Car( int maxSpeed ){
this -> maxSpeed = maxSpeed;
cout << "Constructor: New Car (speed="<<maxSpeed<<") at " << this << endl;
}
// Assignment operator
Car& Car::operator= (const Car &anotherCar){
cout << "Assignment operator: copying " << &anotherCar << " into " << this << endl;
this -> maxSpeed = anotherCar.maxSpeed;
return *this;
}
// Copy constructor
Car::Car(const Car &anotherCar ) {
cout << "Copy constructor: copying " << &anotherCar << " into " << this << endl;
this->maxSpeed = anotherCar.maxSpeed;
}
// Print the car.
void Car::print(){
cout << "Print: Car (speed=" << maxSpeed << ") at " << this << endl;
}
// return automatic object (copy object on return) (STACK)
Car makeNewCarCopy(){
Car c(120);
return c; // object copied and destroyed here
}
// return reference to object (STACK)
Car& makeNewCarRef(){
Car c(60);
return c; // c destroyed here, UNSAFE!
// compiler will say: warning: reference to local variable ā€˜cā€™ returned
}
// return pointer to object (HEAP)
Car* makeNewCarPointer(){
Car * pt = new Car(30);
return pt; // object in the heap, remember to delete it later on!
}
int main(){
Car a(1),c(2);
Car *b = new Car(a);
a.print();
a = c;
a.print();
Car copyC = makeNewCarCopy(); // safe, but requires copy
copyC.print();
Car &refC = makeNewCarRef(); // UNSAFE
refC.print();
Car *ptC = makeNewCarPointer(); // safe
if (ptC!=NULL){
ptC -> print();
delete ptC;
} else {
// NULL pointer
}
}
The code doesn't seem to crash, and I get the following output:
Constructor: New Car (speed=1) at 0x7fff51be7a38
Constructor: New Car (speed=2) at 0x7fff51be7a30
Copy constructor: copying 0x7fff51be7a38 into 0x7ff60b4000e0
Print: Car (speed=1) at 0x7fff51be7a38
Assignment operator: copying 0x7fff51be7a30 into 0x7fff51be7a38
Print: Car (speed=2) at 0x7fff51be7a38
Constructor: New Car (speed=120) at 0x7fff51be7a20
Print: Car (speed=120) at 0x7fff51be7a20
Constructor: New Car (speed=60) at 0x7fff51be79c8
Print: Car (speed=60) at 0x7fff51be79c8
Constructor: New Car (speed=30) at 0x7ff60b403a60
Print: Car (speed=30) at 0x7ff60b403a60
Now, I have the following questions:
Is makeNewCarCopy safe? Is the local object being copied and destroyed at the end of the function? If so, why isn't it calling the overloaded assignment operator? Does it call the default copy constructor?
My guts tell me to use makeNewCarPointer as the most usual way of returning objects from a C++ function/method. Am I right?

Is makeNewCarCopy safe? Is the local object being copied and destroyed
at the end of the function? If so, why isn't it calling the overloaded
assignment operator? Does it call the default copy constructor?
The important question here is "Is makeNewCarCopy safe?" The answer to that question is, "yes." You are making a copy of the object and returning that copy by-value. You do not attempt to return a reference to a local automatic object, which is a common pitfall among newbies, and that is good.
The answers to the other parts of this question are philisophically less important, although once you know how to do this safely they may become critically important in production code. You may or may not see construction and destruction of the local object. In fact, you probably won't, especially when compiling with optimizations turned on. The reason is because the compiler knows that you are creating a temporary and returning that, which in turn is being copied somewhere else. The temporary becomes meaningless in a sense, so the compiler skips the whole bothersome create-copy-destroy step and simply constructs the new copy directly in the variable where it's ultimately intended. This is called copy elision. Compilers are allowed to make any and all changes to your program so long as the observable behavior is the same as if no changes were made (see: As-If Rule) even in cases where the copy constructor has side-effects (see: Return Value Optimization) .
My guts tell me to use makeNewCarPointer as the most usual way of
returning objects from a C++ function/method. Am I right?
No. Consider copy elision, as I described it above. All contemporary, major compilers implement this optimization, and do a very good job at it. So if you can copy by-value as efficiently (at least) as copy by-pointer, is there any benefit to copy by-pointer with respect to performance?
The answer is no. These days, you generally want to return by-value unless you have compelling need not to. Among those compelling needs are when you need the returned object to outlive the "scope" in which it was created -- but not among those is performance. In fact, dynamic allocation can be significantly more expensive time-wise than automatic (ie, "stack") allocation.

Yes, makeNewCarCopy is safe. Theoretically there will be a copy made as the function exits, however because of the return value optimization the compiler is allowed to remove the copy.
In practice this means that makeNewCarCopy will have a hidden first parameter which is a reference to an uninitialized Car and the constructor call inside makeNewCarCopy will actually initialize the Car instance that resides outside of the function's stack frame.
As to your second question: Returning a pointer that has to be freed is not the preferred way. It's unsafe because the implementation detail of how the function allocated the Car instance is leaked out and the caller is burdened with cleaning it up. If you need dynamic allocation then I suggest that you return an std::shared_ptr<Car> instead.

Yes makeNewCarCopy is safe. And in most cases it is effective as compiler can do certain optimizations like copy elision (and that the reason you do not see assignment operator or copy ctor called) and/or move semantics added by C++11
makeNewCarPointer can be very effective, but is is very dangerous at the same time. The problem is you can easily ignore return value and compiler will not produce any warnings. So at least you should return smart pointer like std::unique_ptr or std::shared_ptr. But IMHO previous method is more preferred and would be at least not slower. Different story if you have to create object on heap by different reason.

Related

Destruction of a non-existing object

I am struggling a little bit with move semantics. I read a lot about that topic, however, there are two concrete problems to which I did not found any answers and, thus, like to present them to you.
First, I have the following exemplary code:
#include <iostream>
#include <cstddef>
class A
{
public:
A *ptr;
virtual ~A()
{
std::cout << "dtor" << std::endl;
delete ptr;
ptr=nullptr;
}
};
main()
{
A x, y;
x.ptr = &y;
}
// compile and link like this with g++: g++ -std=c++0x -lstdc++ code.cc
Class A is able to have a member of itself. I use this "composite pattern" concept to build a hierarchy. However, in this case, when object x is destructed, its destructor deletes the pointer to object y. When finally object y should be destructed, it is already which yields an error... How can I solve this?
The second case looks like this:
main()
{
A x, y;
y = std::move(x);
std::cout << "x.ptr: " << x.ptr << std::endl;
std::cout << "y.ptr: " << y.ptr << std::endl;
}
Here, I can see that both references are equal which means both exists. I though that std::move moves the content from x to y. I would have expected that x.ptr is "empty"....?
Thanks in advance!
Cheers
In the first case, both of your x and y objects are created on stack so they will be destructed automatically. However, your class A's destructor uses delete which assumes that the object referred by ptr was created on heap with new.
So it's an error to set x.ptr to refer an object created on stack (like y). A correct code would be
x.ptr = new A;
This is the danger of raw pointers - you can't differentiate between pointers to dynamically allocated objects (that you have to eventually delete) and "just pointers" (that you can't).
It's better if you use std::unique_ptr<A> instead of raw pointer A*.
It will also call delete my itself, so your delete ptr won't be needed.
As for the second case, for primitive types move is actually just a copy. If you move from int to int, or from ptr to ptr, it's just a copy as there is nothing to optimize with move for primitive types, there is no special "emptying" of the moved-from object. But for your case there are good things called smart pointers that actually do "emptying" (because it guarantees correctness). You guessed it - I'm talking about std::unique_ptr.
So again, if you change your ptr from A* to std::unique_ptr<A> then move will do the job you're looking for.
In two words, std::unique_ptr is your real friend here.
In the first, you create two objects of type A on the stack
A x,y;
then assign the address of y to the member x.ptr. When the objects go out of scope, their destructors are called. This happens in the reverse order of their construction, so it should be
y.~A()
x.~A()
In your case, you manually call delete in the destructor, and this will call delete on an already deleted object when execution x.~A().
This not the only problem in your code:
You call delete on an object on the stack. Calls to deletes should be matched by calls to new. Even better, you should manually call new or delete and use std::unique_ptr and std::shared_ptr`.
When b's destructor is called it will delete ptr which uses an uninitialized value for ptr. The compiler-generated constructor does not initialize the ptr tp nullptr. I know at least one compiler which does this in debug mode but in release mode.
When you use std::move, it will finally call the move constructor (or move assignmnet operator). Since you did not define one manually but you define a destructor, there will be no compiler-generated move constructor. So in your case, it will eventually call the implicit copy-constructor and copy the member values, which is what you are seeing.
Even if you add
class A
{
public:
A(A&& a) = default;
A& operator=(A&& a) = default;
A *ptr;
virtual ~A()
{
std::cout << "dtor" << std::endl;
delete ptr;
ptr=nullptr;
}
};
to request compiler-generated move semantics, it will generate code that does a member-wise move, looking like
A(A&& a): ptr( std::move(a.ptr) ) {}
For a pointer type, this just assigns the value to the new variable and leaves the old variable as is. The standard's requirements on a moved object are quite basic and fulfilled by this.

C++ copy constructor double call on member initialization

Consider the below code, where a composing class with another class as its member is being instantiated:
class CopyAble {
private:
int mem1;
public:
CopyAble(int n1) : mem1(n1) {
cout << "Inside the CopyAble constructor" << endl;
}
CopyAble(const CopyAble& obj) {
cout << "Inside the CopyAble copy constructor" << endl;
this->mem1 = obj.mem1;
return *this;
}
CopyAble& operator=(const CopyAble& obj) {
cout << "Inside the CopyAble assignment constructor" << endl;
this->mem1 = obj.mem1;
}
~CopyAble() {};
};
class CopyAbleComposer {
private:
CopyAble memObj;
public:
CopyAbleComposer(CopyAble m1) : memObj(m1) {
cout << "Composing the composer" << endl;
}
~CopyAbleComposer() {}
};
int main()
{
CopyAble ca(10);
CopyAbleComposer cac(ca);
return 0;
}
When I run this, I get the output:
Inside the CopyAble constructor
Inside the CopyAble copy constructor
Inside the CopyAble copy constructor
Composing the composer
Which means that the CopyAble copy constructor is being run twice - once when the CopyAble object is passed into the CopyAbleComposer constructor, and again when the initializer memObj(m1) runs.
Is this an idiomatic use of the copy constructor? It seems very inefficient that the copy constructor runs twice when we try to initialize a member object with a passed-in object of the same type, and it seems like a trap a lot of C++ programmers can easily fall into without realizing it.
EDIT: I don't think this is a duplicate of the question regarding passing a reference into the copy constructor. Here, we are being forced to pass a reference into a regular constructor to avoid duplicate object creation, my question was that is this generally known that class constructors in C++ should have objects passed in by reference to avoid this kind of duplicate copy?
You should accept CopyAble by reference at CopyAbleComposer(CopyAble m1), otherwise a copy constructor will be called to construct an argument. You should also mark it as explicit to avoid accidental invocations:
explicit CopyAbleComposer(const CopyAble & m1)
Pass-by-value and the associated copying is a pretty widely known property of C++. Actually, in the past C++ was criticized for this gratuitious copying, which happened silently, was hard to avoid and could lead to decreased performance. This is humorously mentioned e.g. here:
You accidentally create a dozen instances of yourself and shoot them all in the foot. Providing emergency medical assistance is impossible since you can't tell which are bitwise copies and which are just pointing at others and saying, "That's me, over there."
C++98
When any function/method is declared to receive an argument by value, this sort of copying happens. It doesn't matter if it's a constructor, a "stand-alone" function or a method. To avoid this, use a const reference:
CopyAbleComposer(const CopyAble& m1) : memObj(m1)
{
...
}
Note: even if you rearrange your code as below, one copy always remains. This has been a major deficiency in C++ for a long time.
CopyAbleComposer cac(CopyAble(10)); // initializing mem1 by a temporary object
C++11
C++11 introduced move semantics, which replaces the additional copy by a "move" operation, which is supposed to be more efficient than copy: in the common case where an object allocates memory dynamically, "move" only reassigns some pointers, while "copy" allocates and deallocates memory.
To benefit from optimization offered by move semantics, you should undo the "optimization" you maybe did for C++98, and pass arguments by value. In addition, when initializing the mem1 member, you should invoke the move constructor:
CopyAbleComposer(CopyAble m1) : memObj(std::move(m1)) {
cout << "Composing the composer" << endl;
}
Finally, you should implement the move constructor:
CopyAble(CopyAble&& obj) {
cout << "Inside the CopyAble move constructor" << endl;
this->mem1 = obj.mem1;
}
Then you should see that the "copy" message doesn't appear, and is replaced by the "move" message.
See this question for more details.
Note: In all these examples, the CopyAble objects are assumed to be much more complex, with copy and move constructors doing non-trivial work (typically, resource management). In modern C++, resource management is considered a separate concern, in the context of separation of concerns. That is, any class that needs a non-default copy or move constructor, should be as small as possible. This is also called the Rule of Zero.

Side effects of assigning a pointer value to a variable in C++

I'm running into some strange problems when assigning the reference of a pointer to a variable: the local code works correctly, but it causes memory access errors elsewhere:
//This works fine
Gridcell* g = model.gc;
cout << g->LC_updated << " " << g << endl;
//When I include this, the program crashes elsewhere
//But output from this line is OK
Gridcell gc = *g;
cout << "Var:" << gc.LC_updated << &gc << endl;
(Gridcell is a class, which doesn't have a no-args constructor)
I'm not a C++ expert, and this is a fairly large external library, but I can't understand why an assignment to a locally scoped variable should cause problems elsewhere. Can anyone shed some light on this?
You don't give enough information to solve the problem. There is nothing inherently wrong with the code you've posted.
My guess is that Gridcell lacks a proper copy constructor and so when gc goes out of scope it deletes things that *g is still referring to.
This line of code:
Gridcell gc = *g;
is where the copy constructor is being invoked. It's essentially equivalent to saying this:
Gridcell gc(*g);
which invokes the Gridcell::Gridcell(const Gridcell &) constructor, otherwise known as the copy constructor. The copy constructor is special in that if you don't have one, the compiler will automatically generate one for you. The automatically generated one typically just invokes the copy constructor of each individual member variable, including the pointers. For basic types, like int or Foo *, the copy constructor simply makes an exact copy.
For example, if you have code like this:
class Foo {
public:
Foo() : msg_(new char[30]) { strcpy(msg_, "I'm Foo!"); }
~Foo() { delete [] msg_; }
private:
char *msg_;
};
void aFunction(Foo *aFoo)
{
Foo myfoo = *aFoo;
}
void anotherFunction()
{
Foo localfoo;
aFunction(&localfoo);
}
It will crash. localfoo will allocate character array. The line Foo myfoo = *aFoo will call the copy constructor which will make a straight copy of the pointer. Then the destructor for myfoo will be called and the memory will be freed. Then the destructor for localfoo will be called and the memory will be freed again, resulting in a crash on many systems.
You need to make sure that Gridcell has a proper copy constructor. This is only required if Gridcell manually manages resources, which almost never should be the case. If it the the case for you, you will need The Big Three.
If you need more specific help, post the class definition of Gridcell, along with constructors and destructor, if you have them.
If your intention is not to copy, you can use a reference:
Gridcell & gc = *g;
cout << "Var:" << gc.LC_updated << &gc << endl;
The usage is the same, but it will not create copy.
Is model.gc a local variable?
If so, when it goes out of scope it ceases to exist. And any pointers to it are no longer valid.
#Space_C0wb0y is right.
Imagine that you have attributes in your Gridcell class that are pointers (arrays or objects that are explicitly allocated through new).
When you assgin an object of type Gridcell from another one, the default copy constructor makes a shallow copy. It copies the value of those pointers, but does not create new objects/arrays for the new attributes of yout new object.
If you split
cout << "Var:" << gc.LC_updated << &gc << endl;
in two lines:
cout << "&gc" <<&gc << endl;
cout << "Var:" << gc.LC_updated << endl;
You will probably see that the fault goes to the line where your reference LC_updated (I don't know what is it).
Check your constructors to see how it is being initialized.
This line:
GridCell gc = *g;
Does a copy of the instance pointed by g. If the GridCell does not define a copy-constructor (a constructor of signature GridCell(const GridCell& other)), then a default one is provided by the compiler that does a copy of each member. For member that are of a pointer type, this is just a copy of the pointer, and thus both gc and the instance pointed by g will point to the same memory.
When the gc variable goes out of scope, its destructor is called. If the GridCell class does manage some memory, does not provide a copy-constructor (or it is incorrect), and release the memory in its destructor, then the GridCell instance pointed by g will point to released memory after this point.
Generally, when a class manage some memory, it must override the destructor, the copy-constructor and the assignment operator. This is the rule of three.
Please note that the assignment will also perform slicing if g point to a subclass of GridCell and that can also bring other problems. If you want to use the gc variable as an alias not to have to use *g everywhere, you should consider using a reference (or a const-reference) instead of making a copy (especially if the object does manager lots of memory, copy can be expensive).

Accessing an object in operator new

My professor in C++ has shown us this as an example in overloading the operator new (which i believe is wrong):
class test {
// code
int *a;
int n;
public:
void* operator new(size_t);
};
void* test::operator new(size_t size) {
test *p;
p=(test*)malloc(size);
cout << "Input the size of array = ?";
cin >> p->n;
p->a = new int[p->n];
return p;
}
Is this right?
It's definitely "not right", in the sense that it's giving me the creeps.
Since test has no user-declared constructors, I think it could work provided that the instance of test isn't value-initialized (which would clear the pointer). And provided that you write the corresponding operator delete.
It's clearly a silly example, though - user interaction inside an overloaded operator new? And what if an instance of test is created on the stack? Or copied? Or created with test *tp = new test(); in C++03? Or placement new? Hardly user-friendly.
It's constructors which must be used to establish class invariants (such as "I have an array to use"), because that's the only way to cover all those cases. So allocating an array like that is the kind of thing that should be done in a constructor, not in operator new. Or better yet, use a vector instead.
As far as the standard is concerned - I think that since the class is non-POD the implementation is allowed to scribble all over the data in between calling operator new and returning it to the user, so this is not guaranteed to work even when used carefully. I'm not entirely sure, though. Conceivably your professor has run it (perhaps many years ago when he first wrote the course), and if so it worked on his machine. There's no obvious reason why an implementation would want to do anything to the memory in the specific case of this class.
I believe that is "wrong" because he
access the object before the
constructor.
I think you're correct on this point too - casting the pointer returned from malloc to test* and accessing members is UB, since the class test is non-POD (because it has private non-static data members) and the memory does not contain a constructed instance of the class. Again, though, there's no reason I can immediately think of why an implementation would want to do anything that stops it working, so I'm not surprised if in practice it stores the intended value in the intended location on my machine.
Did some Standard checking. Since test has private non-static members, it is not POD. So new test default-initializes the object, and new test() value-initializes it. As others have pointed out, value-initialization sets members to zero, which could come as a surprise here.
Default-initialization uses the implicitly defined default constructor, which omits initializers for members a and n.
12.6.2p4: After the call to a constructor for class X has completed, if a member of X is neither specified in the constructor's mem-initializers, nor default-initialized, nor value-initialized, nor given a value during execution of the body of the constructor, the member has indeterminate value.
Not "the value its memory had before the constructor, which is usually indeterminate." The Standard directly says the members have indeterminate value if the constructor doesn't do anything about them.
So given test* p = new test;, p->a and p->n have indeterminate value and any rvalue use of them results in Undefined Behavior.
The creation/destruction of objects in C++ is divided into two tasks: memory allocation/deallocation and object initialization/deinitialization. Memory allocation/deallocation is done very differently depending on an object's storage class (automatic, static, dynamic), object initialization/deinitialization is done using the object's type's constructor/destructor.
You can customize object initialization/deinitialization by providing your own constructors/destructor. You can customize the allocation of dynamically allocated objects by overloading operator new and operator delete for this type. You can provide different versions of these operators for single objects and arrays (plus any number of additional overloads).
When you want to fine-tune the construction/destruction of objects of a specific type you first need to decide whether you want to fiddle with allocation/deallocation (of dynamically allocated objects) or with initialization/deinitialization. Your code mixes the two, violating one of C++' most fundamental design principle, all established praxis, every known C++ coding standard on this planet, and your fellow-workers' assumptions.
Your professor is completely misunderstanding the purpose of operator new whose only task is to allocate as much memory as was asked and to return a void* to it.
After that the constructor is called to initialize the object at that memory location. This is not up to the programmer to avoid.
As the class doesn't have a user-defined constructor, the fields are supposed to be uninitialized, and in such a case the compiler has probably freedom to initialize them to some magic value in order to help finding use of uninitialized values (e.g for debug builds). That would defeat the extra work done by the overloaded operator.
Another case where the extra work will be wasted is when using value-initialization: new test();
This is very bad code because it takes initialization code that should be part of a constructor and puts it in operator new which should only allocate new memory.
The expression new test may leak memory (that allocated by p->a = new int[p->n];) and the expression new test() definitely will leak memory. There is nothing in the standard that prevents the implementation zeroing, or setting to an alternate value, the memory returned by a custom operator new before that memory is initialized with an object even if the subsequent initialization wouldn't ordinarily touch the memory again. If the test object is value-initialized the leak is guaranteed.
There is also no easy way to correctly deallocate a test allocated with new test. There is no matching operator delete so the expression delete t; will do the wrong thing global operator delete to be called on memory allocated with malloc.
This does not work.
Your professor code will fail to initialize correctly in 3/4 of cases.
It does not initialize objects correctly (new only affects pointers).
The default constructor generated for tests has two modes.
Zero Initialization (which happens after new, but POD are set to zero)
Default Initialization (POD are uninitialized)
Running Code (comments added by hand)
$ ./a.exe
Using Test::new
Using Test::new
A Count( 0) // zero initialized: pointer leaked.
A Pointer(0)
B Count( 10) // Works as expected because of default init.
B Pointer(0xd20388)
C Count( 1628884611) // Uninitialized as new not used.
C Pointer(0x611f0108)
D Count( 0) // Zero initialized because it is global (static storage duration)
D Pointer(0)
The Code
#include <new>
#include <iostream>
#include <stdlib.h>
class test
{
// code
int *a;
int n;
public:
void* operator new(size_t);
// Added dredded getter so we can print the values. (Quick Hack).
int* getA() const { return a;}
int getN() const { return n;}
};
void* test::operator new(size_t size)
{
std::cout << "Using Test::new\n";
test *p;
p=(test*)malloc(size);
p->n = 10; // Fixed size for simple test.
p->a = new int[p->n];
return p;
}
// Objects that have static storage duration are zero initialized.
// So here 'a' and 'n' will be set to 0
test d;
int main()
{
// Here a is zero initialized. Resulting in a and n being reset to 0
// Thus you have memory leaks as the reset happens after new has completed.
test* a = new test();
// Here b is default initialized.
// So the POD values are undefined (so the results are what you prof expects).
// But the standard does not gurantee this (though it will usually work because
// of the it should work as a side effect of the 'zero cost principle`)
test* b = new test;
// Here is a normal object.
// New is not called so its members are random.
test c;
// Print out values
std::cout << "A Count( " << a->getN() << ")\n";
std::cout << "A Pointer(" << a->getA() << ")\n";
std::cout << "B Count( " << b->getN() << ")\n";
std::cout << "B Pointer(" << b->getA() << ")\n";
std::cout << "C Count( " << c.getN() << ")\n";
std::cout << "C Pointer(" << c.getA() << ")\n";
std::cout << "D Count( " << d.getN() << ")\n";
std::cout << "D Pointer(" << d.getA() << ")\n";
}
A valid example of what the professor failed to do:
class test
{
// code
int n;
int a[1]; // Notice the zero sized array.
// The new will allocate enough memory for n locations.
public:
void* operator new(size_t);
// Added dredded getter so we can print the values. (Quick Hack).
int* getA() const { return a;}
int getN() const { return n;}
};
void* test::operator new(size_t size)
{
std::cout << "Using Test::new\n";
int tmp;
std::cout << How big?\n";
std::cin >> tmp;
// This is a half arsed trick from the C days.
// It should probably still work.
// Note: This may be what the professor should have wrote (if he was using C)
// This is totally horrible and whould not be used.
// std::vector is a much:much:much better solution.
// If anybody tries to convince you that an array is faster than a vector
// The please read the linked question below where that myth is nailed into
// its over sized coffin.
test *p =(test*)malloc(size + sizeof(int) * tmp);
p->n = tmp;
// p->a = You can now overflow a upto n places.
return p;
}
Is std::vector so much slower than plain arrays?
As you show this is wrong. You can also see how easy it is to get this wrong.
There usually isn't any reason for it unless you are trying to manage your own memory allocations and in a C++ environment you would be better off learning the STL and write custom allocators.

how to get stl map to construct/destruct inserted object only once

I have found a very prejudicial fact about stl maps. For some reason I cant get objects being inserted in the map to get constructed/destructed only once.
Example:
struct MyObject{
MyObject(){
cout << "constructor" << endl;
}
~MyObject(){
cout << "destructor" << endl;
}
};
int main() {
std::map<int, MyObject> myObjectsMap;
myObjectsMap[0] = MyObject();
return 0;
}
returns:
constructor
destructor
destructor
constructor
destructor
If I do:
typedef std::pair<int, MyObject> MyObjectPair;
myObjectsMap.insert( MyObjectPair(0,MyObject()));
returns:
constructor
destructor
destructor
destructor
I'm inserting Objects responsible for their own memory allocation, so when destructed they'll clean themselves up, being destructed several times is causing me some trouble.
I suggest you add a copy constructor - that's what is being used for the 'missing' constructions I think.
Code:
#include <iostream>
#include <map>
using namespace std;
struct MyObject{
MyObject(){
cout << "no-arg constructor" << endl;
}
MyObject(const MyObject&) {
cout << "const copy constructor" << endl;
}
~MyObject(){
cout << "destructor" << endl;
}
};
int main() {
std::map<int, MyObject> myObjectsMap;
myObjectsMap[0] = MyObject();
return 0;
}
Output:
no-arg constructor
const copy constructor
const copy constructor
destructor
destructor
no-arg constructor
destructor
destructor
std::map is allowed to make as many copies of your objects as it wishes. This is implementation defined and you have no control over this. The "missing" constructions you notice, by the way, may be for calling the copy-constructor, which you didn't define.
What you can do, however is use a flyweight so constructing an object in fact fetches a existing object from a pool of pre-existing objects, and destructing an object does nothing. The pool never frees its objects, but it always maintains a handle over all of them. This way, your memory usage is large from start to stop, but it doesn't change much throughout the life of the program.
To be able to be used in a standard container your objects must be copyable and assignable. If your objects don't conform to this you may are likely to have problems.
That said, if (as your sample code indicates) you just need a default constructed object inserted in the map you can just use operator[] for its side effect:
// Insert default constructed MyObject at key 0
myObjectsMap[0];
Edit
I'm not quite clear from your question, but if you're unclear about the number of objects constructed and believe there is a constructor/destructor mismatch then note that the compiler will provide a copy constructor which doesn't log to std::cout as you don't provide a user-declared one.
When you say myObjectsMap[0], you are calling the default constructor for MyObject. This is because there is nothing in [0] yet, and you just accessed it. It's in the manual.
When you hit MyObject(); you are creating a temporary MyObject instance using the default constructor.
Because you allowed the compiler to define your copy constructor, you see more destructor than constructor messages. (There can only be one destructor, but many constructors, unlike building a house.) If you object should never be copied this way, then you likely want to declare a private copy constructor and copy assignment operator.
You're calling the default constructor and the copy constructor twice each with this code:
myObjectsMap[0] = MyObject();
When you do this:
myObjectsMap.insert( MyObjectPair(0,MyObject()));
you call the default constructor once and the copy constructor 3 times.
You should likely use pointers as map values instead of the objects themselves, in particular I suggest looking at shared_ptr.
note: tests were done using GCC 3.4.5 on a Windows NT 5.1 machine.
That's the way map and the other containers work, you can't get around it. That's why std::auto_ptr can't be used in a collection, for example.