Why does the C++11 move constructor copy by value? - c++

I thought the following example would have the same result as std::map::emplace(), but it didn't:
struct MoveTest {
MoveTest():
var(true)
{
cout << "ctor: " << static_cast<void*>(&var) << endl;
}
MoveTest(MoveTest&& mt):
var(std::move(mt.var))
{
cout << "move ctor: " << static_cast<void*>(&var) << endl;
}
bool var;
};
int main() {
map<int, MoveTest> mtest;
mtest.insert(make_pair(1, MoveTest()));
return 0;
}
output:
ctor: 0x7fff12e4e19b
move ctor: 0x7fff12e4e194
move ctor: 0x25f3034
The MoveTest::var has a different address in each move. It doesn't look like a "move". What's wrong in my code or understanding?

For MoveTest as you've defined it, there's not really much a move ctor (or assignment operator) can optimize (or do in general--all it can really do is copy from source go destination).
Moving is mostly a big win when an object contains a pointer to a bunch of external memory that's (for example) allocated on the heap. In this case, the move ctor/assignment operator can basically do a shallow copy (i.e., just grab the pointer from the moved-from object) instead of a deep copy (copying all the data referred to by that pointer).
For example:
class move_tst {
int *buffer;
static const int size = 1024 * 1024;
public:
move_tst() {
buffer = new int[size];
std::iota(buffer, buffer + size, 0);
}
move_tst(move_tst const &other) {
buffer = new int[size];
std::copy_n(other.buffer, size, buffer);
}
#ifdef MOVE
move_tst(move_tst &&other) {
buffer = other.buffer;
other.buffer = nullptr;
}
#endif
~move_tst() {
delete [] buffer;
}
};
Caveat: I've used a raw invocation of new and a raw pointer here so nothing else gets involved and we wouldn't (for example) get move semantics courtesy of a smart pointer. For normal code under normal circumstances, you should not be using either (raw pointer or raw invocation of new, I mean).
Edit: as far as what std::move does, it doesn't actually do a move itself--it just signals that you no longer care about a value, so it's eligible to be the source of a move, even if that destroys its value.
For example, with the class above, you could do a test like:
for (int i = 0; i < 1000; i++) {
move_tst src;
move_tst dst =src;
}
...and compare it to:
for (int i = 0; i < 1000; i++) {
move_tst src;
move_tst dst = std::move(src);
}
Without the std::move, dst will be created as a copy of src, but with the std::move, it'll be able to do a move from src to dst.

Your log simply tells that you create a temporary MoveTest instance with the default constructor
MoveTest()
which is then copied elsewhere, inside a pair object
make_pair(1, MoveTest())
and copied again somewhere inside the map object
mtest.insert(make_pair(1, MoveTest()));
There are three constructor invocations for three distinct MoveTest instances, each with its own address. As already well explained, whether the constructors are move constructors or old style copy constructors doesn't matter.
Did you expect some of the copies to be optimized away? With nontrivial code in the constructors it becomes unlikely; in particular, reading &var is a good reason to avoid shortcuts.

Related

Copying an array from a struct which is senŠµ through a function

I have want to send a struct to json->setInformation but my program crashes when i try to copy the array which is inside the struct. The rest of the data is okay its just the array which makes the crash occur.
info = data->getInformation();
json->setInformation(info);
getInformation returns a struct which i can read in main.cpp
when i try to send this struct to setInformation it crashes...
information.h which holds my struct
struct information{
String location;
String protocol;
uint8_t groupID;
uint8_t* data;
information& operator=(const struct information& that){
location = that.location;
protocol = that.protocol;
groupID = that.groupID;
for (int i = 0; i < 9; ++i){
data[i] = that.data[i];
}
return *this;
}
};
json.cpp
void JSON::setInformation(information data){
info->location = data.location;
info->protocol = data.protocol;
info->groupID = data.groupID;
// for (int i = 0; i < 9; ++i){
// info->data[i] = data.data[i];
// }
// Serial.print("after JSON: ");
// Serial.println(info->data[0]);
}
this code works fine but when i uncomment the for lop which should copy the array it crashes
Did you allocate memory for your uint8_t data* parameter before using it ?
Then remember to deallocate memory when you don't need it anymore, thus avoiding memory leaks.
Your object is passed by copy to the function, but you have no copy constructor.
Default copy constructor will not copy you raw pointer correctly. So either you declare and implement a copy constructor, either you replace your raw pointer (uint8_t*) by a vector (std::vector<uint8_t>) which is safely copyiable (then copying the object will become a valid operation).
Moreover, we can't see who's allocating/deallocating your raw pointer, but I suspect you are missing a destructor function too.
Your code breaks the rule of three which is the minimal requirement for any class you'll declare in C++.

Buffer Overrun with delete []

I tried to search same questions, but not one helped me. When I run program I get the "A Buffer Overrun has occurred..." error.
Constr:
Player(char* n)
{
length = strlen(n);
name = new char[length+1];
for(unsigned int i(0); i < length; i++)
name[i] = n[i];
name[length] = '\0';
}
Destr:
~Player(void)
{
delete [] name;
}
I've NULL terminated string and don't get out of bounds, what is problem?
There's no obvious error in the code you've posted, but trying to manage dynamic memory by juggling raw pointers will almost inevitably lead to errors like this.
Perhaps you haven't correctly implemented or deleted the copy constructor and copy-assignment operator, per the Rule of Three. In that case, copying a Player object will give two objects with pointers to the same array; both of them will try to delete that array, giving undefined behaviour.
The simplest solution is to manage your string with a class designed for managing strings. Change the type of name to std::string, and then the constructor can simply be something like
explicit Player(std::string const & n) : name(n) {}
and there's no need to declare a destructor (or move/copy constructor/assignment operators) at all.
So... a solution by using an std::string has been provided, but let me give another solution, keeping your member variables intact.
The problem is this. Suppose you have this code somewhere:
Player p1("Bob"); // Okay
Player p2("Annie"); // Okay
p2 = p1; // Oops! (1)
Player p3(p1); // Oops! (2)
At (1), the method Player& Player::operator=(const Player&) is called. Since you didn't provide one, the compiler generates one for you. When it does, it simply assumes that it may copy over all member variables. In this case, it copies over Player::name and Player::length. So, we have p1.name == p2.name. Now when the destructor of p2 is called, the allocated memory pointed to by p2.name is deleted. Then when the destructor of p1 is called, the same memory will be deleted (since p1.name == p2.name)! That's illegal.
To fix this, you can write an assignment operator yourself.
Player& Player::operator = (const Player& other)
{
// Are we the same object?
if (this == &other) return *this;
// Delete the memory. So call the destructor.
this->~Player();
// Make room for the new name.
length = other.length;
name = new char[length + 1];
// Copy it over.
for (unsigned int i = 0; i < length; ++i) name[i] = other.name[i];
name[length] = '\0';
// All done!
return *this;
}
At (2), the same problem occurs. You do not have a copy constructor, so the compiler generates one for you. It will also assume that it may copy over all the member variables, so when the destructors get called, they'll try to delete the same memory again. To fix this, also write a copy constructor:
Player::Player(const Player& other)
{
if (this == &other) return;
length = other.length;
name = new char[length + 1];
for (unsigned int i = 0; i < length; ++i) name[i] = other.name[i];
}
At the end of the day you should use an std::string though.

Different Destructor Types?

I have an object called a Chunk that holds a pointer to a b2Body. It does other important things, but i removed those for simplicity. Heads up, smart pointers won't work(I think), you'll see why.
class DChunk
{
public:
DChunk();
DChunk(const DChunk& old);
virtual ~DChunk();
virtual b2Body* getBody() const;
private:
b2Body* m_pBody;//pointer;
};
The question is, how to define when to delete the m_pBody object.
If I want to copy this object, like say there is a vector of these things and I push_back another, it will call the Copy Constructor, copy the memory address of m_pBody(thats what i want), and then delete the old one. If the Destructor on this object deletes m_pBody, that's obviously bad, because the new copy wont have a valid memory address, but if it doesn't delete it, then m_pBody will never be deleted, and it needs to be deleted when there are no more Chunks pointing at it.
The only correct way to delete the m_pBody object is to call m_pBody->GetWorld()->DestroyBody( m_pBody ); and thats not under my control, so smart pointers dont really work.
I was hoping there would be different types of destructors that get called appropriately, like when a copy has been made in a vector. Also, there should never be more than one Chunk associated with one b2Body, if that is helpful.
I will assume you have something like
vector<DChunck> myvec;
and you are worried about doing
obj=DChunk()
myvec.push_back(obj)
First of all (this is very beginner friendly approach, avoiding smart pointers or any C++11) there's something not quite correct about creating a container DChunk objects. That's because when you declare
vector<DChunk>
you are telling your vector that it will receive objects the size of DChunk.
However, since that class contains a pointer to an array, m_pBody (array's size will not be constant!), this approach will not be too "healthy" for C++.
Given this, you can do something else, sticking to your class design: create a container of pointers!
You can create
vector<DChunk*> myvec;
and if you want to add an object to that vector, you just do
DChunk *obj = new DChunk();
myvec.push_back(event);
since now the container is handling pointers, which can be juggled around without interfering with the objects content, avoiding the worries concerning a destructor.
Calling an object's method will now be, for example,
(*myvec[3]).getBody()
or (cleaner version)
myvec[3]->getBody()
Hope I addressed your question
You can also provide move constructor so that instead of copying, it would move stuff... Here's an example that I made some hours ago, because I had the same problem (I didn't know in what order would these constructors and when be called, also "&&" is move constructor):
A move constructor is similar to copy constructor. The difference is that in move constructor instead of copying values and stuff, you assign given object's pointers (not copy) and values to a new one (this->temp = OldClass.temp) and then make OldClass.temp = NULL; so that when the unavoidable destructor is called, it finds a NULL pointer and does not delete it.
#include <iostream>
#include <Windows.h>
class MyClass
{
public:
MyClass()
{
temp = new RECT();
ZeroMemory(temp, sizeof(RECT));
}
MyClass(int x, int y)
{
temp = new RECT();
ZeroMemory(temp, sizeof(RECT));
temp->left = x;
temp->top = y;
}
MyClass(MyClass &&OldClass)
{
if (this->temp != NULL)
{
delete this->temp;
this->temp = NULL;
}
temp = OldClass.temp;
OldClass.temp = NULL;
}
MyClass& operator=(MyClass &&OldClass)
{
if (this->temp != NULL)
{
delete this->temp;
this->temp = NULL;
}
temp = OldClass.temp;
OldClass.temp = NULL;
return *this;
}
MyClass(const MyClass &OldClass)
{
*temp = *OldClass.temp;
}
MyClass& operator=(const MyClass &OldClass)
{
*temp = *OldClass.temp;
return *this;
}
~MyClass()
{
if (this->temp != NULL)
{
delete this->temp;
this->temp = NULL;
}
}
void Print()
{
std::cout << temp << " " << temp->left << " " << temp->top << " " << temp->right << " " << temp->bottom << '\n';
}
private:
RECT *temp;
};
int main()
{
MyClass bla, cha(54, 48);
bla.Print();
cha.Print();
bla = MyClass(2, 2);
bla.Print();
bla = cha;
bla.Print();
cha = MyClass(54, 2);
cha.Print();
std::cin.get();
return 0;
}
In common, a proper memory management is non trivial task and no universal decision are existing. Some simple and common well-known methods are presented as "smart pointer" types in newest libraries (and you can also define them yourself (by copy known "standard definition")). But it also is not an completely universal :-)
And your question seems to be a question for a such universal solution.
Some other programming languages (java ... , not C++) advertise you to get rid of that problem (by the built-in methods of language implementations).
You write: "Also, there should never be more than one Chunk associated with one b2Body, if that is helpful." . And then the problem seems to disappear (because the Chunk cannot be copied at all). (?)

C++ helper function for copy constructor

I haven't been able to find a good answer to this question.
I'm working on a C++ program and I'm trying to implement a function named copy which takes a reference to another object as an argument. Then, it returns a deep copy of this object.
Some background on my project: the Scene class contains a dynamic array (called "Images") of pointers to either NULL or an instance of the Image class, which is not shown here - but works as it should (it inherits all of its methods from a third party library, EasyBMP)
The reason I'm doing this is to avoid duplicating code in two places, but it's very possible that I'm taking the wrong approach.
I call this function in my assignment operator:
Scene const & Scene::operator=(Scene const & source)
{
if (this != &source) {
clear();
copy(source);
}
return *this;
}
And my copy constructor:
Scene::Scene(Scene const & source)
{
copy(source);
}
Finally, my copy() method looks like this:
Scene const & Scene::copy(Scene const & source)
{
Scene res(source.Max);
for (int i=0; i<res.Max; i++)
{
delete res.Images[i];
if (source.Images[i] != NULL)
res.Images[i] = new Image(*(source.Images[i]));
else
res.Images[i] = NULL;
}
return res;
}
Currently, it does NOT work. One problem I can see is that I'm trying to return a variable that goes out of scope as soon as the copy function ends. I tried returning a reference before, but the compiler threw errors and this wouldn't help with the scope issue anyways.
But I'm not even sure that my logic is right, i.e. can you even do something like this in a constructor? Or should I just explicitly write out the code in the copy constructor and assignment operator (without implementing the helper method copy)?
I'm very new to C++ and pointers, so any guidance would be much appreciated.
There's a way easier and more idiomatic way to do what you want: the copy-and-swap idiom.
// N.B. Not tested, but shows the basic structure of the copy-and-swap idiom.
class Scene
{
public:
Scene(int)
{
// Initialize a pointer array of Images
}
~Scene()
{
// Get rid of our pointer array of Images
}
// Copy constructor
// N.B. Not exception safe!
Scene(const Scene& rhs) : imgPtrArray(new Image*[rhs.max])
{
// Perform deep copy of rhs
for (int i=0; i < rhs.max; ++i)
{
if (rhs.imgPtrArray[i] != 0)
imgPtrArray[i] = new Image(*(rhs.imgPtrArray[i]));
else
imgPtrArray[i] = 0;
}
}
// Copy assignment constructor
// When this is called, a temporary copy of Scene called rhs will be made.
// The above copy constructor will then be called. We then swap the
// members so that this Scene will have the copy and the temporary
// will destroy what we had.
Scene& operator=(Scene rhs)
{
swap(rhs);
return *this;
}
void swap(Scene& rhs)
{
// You can also use std::swap() on imgPtrArray
// and max.
Images** temp = imgPtrArray;
imgPtrArray = rhs.imgPtrArray;
rhs.imgPtrArray = temp;
int maxTemp = max;
max = rhs.max;
rhs.max = maxTemp;
}
private:
Images** imgPtrArray;
int max;
};
That being said, I highly recommend that you pick up a good introductory C++ book, which will cover the basics of implementing the copy constructor and copy assignment operators correctly.
Scene const & Scene::operator=(Scene const & source);
overloaded assignment operator copies the content of this to the argument received source. For copy there is no need to return any thing or to create a local object. Just make a member wise copy from this to source.
void Scene::copy(Scene const & source){
// Member wise copy from this to source
}
Rule of three should be helpful to better understand more about these.

C++ basics, vectors, destructors

I'm a little confused about the best practice for how to do this. Say I have a class that for example allocs some memory. I want it to self destruct like an auto but also put it in a vector for some reason unknown.
#include <iostream>
#include <vector>
class Test {
public:
Test();
Test(int a);
virtual ~Test();
int counter;
Test * otherTest;
};
volatile int count = 0;
Test::Test(int a) {
count++;
counter = count;
std::cout << counter << "Got constructed!\n";
otherTest = new Test();
otherTest->counter = 999;
}
Test::Test() {
count++;
counter = count;
std::cout << counter << "Alloced got constructed!\n";
otherTest = NULL;
}
Test::~Test() {
if(otherTest != 0){
std::cout << otherTest->counter << " 1Got destructed" << counter << "\n";
otherTest->counter = 888;
std::cout << otherTest->counter << " 2Got destructed" << counter << "\n";
}
}
int vectorTest(){
Test a(5);
std::vector<Test> vecTest;
vecTest.push_back(a);
return 1;
}
int main(){
std::cout << "HELLO WORLD\n";
vectorTest();
std::cout << "Prog finished\n";
}
In this case my destructor gets called twice all from counter 1, the alloc' object has already been set to 888 (or in a real case freed leading to bad access to a deleted object). What's the correct case for putting a local variable into a vector, is this some kind of design that would never happen sensibly. The following behaves differently and the destructor is called just once (which makes sense given its an alloc).
int vectorTest(){
//Test a(5);
std::vector<Test> vecTest;
vecTest.push_back(*(new Test(5)));
return 1;
}
How can I make the local variable behave the same leading to just one call to the destructor? Would a local simply never be put in a vector? But aren't vectors preferred over arrays, what if there are a load of local objects I want to initialize separately and place into the vector and pass this to another function without using free/heap memory? I think I'm missing something crucial here. Is this a case for some kind of smart pointer that transfers ownership?
A vector maintains its own storage and copies values into it. Since you did not implement a copy constructor, the default one is used, which just copies the value of the pointer. This pointer is thus deleted twice, once by the local variable destructor and once by the vector. Don't forget the rule of three. You either need to implement the copy and assignment operators, or just use a class that already does this, such as shared_ptr.
Note that this line causes a memory leak, since the object you allocated with new is never deleted:
vecTest.push_back(*(new Test(5)));
In addition to what Dark Falcon wrote: To avoid reallocating when inserting into a vector, you typically implement a swap function to swap local element with a default-constructed one in the vector. The swap would just exchange ownership of the pointer and all will be well. The new c++0x also has move-semantics via rvalue-references to help with this problem.
More than likely, you'd be better off having your vector hold pointers to Test objects instead of Test objects themselves. This is especially true for objects (like this test object) that allocate memory on the heap. If you end up using any algorithm (e.g. std::sort) on the vector, the algorithm will be constantly allocating and deallocating memory (which will slow it down substantially).