Why can I use memcpy to copy one object variable to another - c++

I have this class
class TestClass
{
public:
int* tab;
};
int main()
{
TestClass a;
a.tab[0]=8;
a.tab[1]=5;
TestClass b;
memcpy(b.tab,a.tab,sizeof(int)*2);
cout << b.tab[0] << endl;
return 0;
}
and I want to copy tab from a to b tab. But this code doesn't work.
I tried to copy tab to dynamic array and it worked.
TestClass a;
a.tab[0]=8;
a.tab[1]=5;
int* b=new int[2];
memcpy(b,a.tab,sizeof(int)*2);
cout << b[0] << endl;
Can someone explain why first code doesn't work but second works?

You're causing undefined behavior by trying to use the subscript operator with an uninitialized pointer. Instead of doing any of these, use std::vector or std::array, depending on what you are trying to achieve:
#include <iostream>
#include <vector>
class TestClass
{
public:
std::vector<int> tab;
};
int main()
{
TestClass a{ { 8, 5 } };
TestClass b{ a };
std::cout << b.tab[0] << '\n';
}
This keeps it simple and maintainable. STL containers have more friendly value semantics and they are in general easier to use, harder to abuse.

Related

Is it safe to return a vector of std::shared_ptr?

Is my code in risk of memory-leak for returning vector of std::shared_ptr? I think it's safe because the reference count will not be zero till the end of main function. Am I right?
#include <iostream>
#include <vector>
#include <memory>
using namespace std;
class A {
public:
A(int v):a(v){}
int a;
};
typedef std::shared_ptr<A> APtr;
vector<APtr> test() {
APtr x(new A(1));
APtr y(new A(2));
APtr z(new A(3));
APtr a(new A(4));
return vector<APtr>({x, y, z, a});
}
int main()
{
cout << "Hello World" << endl;
vector<APtr> b = test();
for(auto k : b) {
cout << k->a << "\n";
}
return 0;
}
Yes, this is safe and memory-leak free. Your test function creates the pointers, and they'll all have a reference count of one. Once the function returns, they're copied into b which increases the reference count, then they go out of scope and decrease the reference count back down to 1. The A are all cleaned up correctly at the end of main.
Putting a breakpoint (or cout statement) in ~A should also show you this correctly. One final minor note, you should prefer make_shared over new

Pointer to a Vector of Class - I can't reach the members of the Class

I try to create a vector with a pointer (so that everything is stored in/on the heap). I then want to fill the vector with an array of a class. I am thinking about accessing the class by class[i].member... Sadly, it does not work.
If I try this without a vector it works, like in:
tClass *MyClass = new tClass[5]
I am trying this without a specific purpose and only to understand C++ better. Can anyone have a look where I am wrong? Thanks!
Here is the code:
#include "iostream"
#include "vector"
using namespace std;
class tClass
{
private:
int x = 0;
public:
int y = 0;
tClass(){cout << "New" << endl;};
~tClass(){}; //do I need to make a delete here?
int main ()
{
vector<tClass> *MyClass[5];
MyClass = new vector<tClass>[5];
cout << MyClass[3].y << endl;
delete[] MyClass;
}
as others have suggested if you want just a vector of tClass you would do the following
vector<tClass> vectorName (5);
and access it like so
vectorName[3].y;
however if you wanted a vector of tClass pointers you would initialise and acess it like this
vector<tClass*> vectorName(5);
vectorName[3]->y;
edit
this might help you a bit more, this is your code, with comment to help you understand what is going wrong
class tClass
{
private:
int x = 0;
public:
int y = 0;
tClass(){ cout << "New" << endl; };
~tClass(){}; //do I need to make a delete here? //no you dont need to make a delete here as this class contains no "news"
int main()
{
vector<tClass> *MyClass[5]; //use () to give a vector an initial size, [] is only to access a member
//also to have a vector holding pointers, the asterisk needs to be after tClass not before the vector name
MyClass = new vector<tClass>[5];
cout << MyClass[3].y << endl; //discused above
delete[] MyClass; //only needed if a new is used, however you dont need one here, as it will just go out of scope
}
here is you code, but fixed to compile and run with the use of pointers
#include <iostream>
#include <vector>
using namespace std;
class tClass
{
private:
int x = 0;
public:
int y = 0;
tClass(){ cout << "New" << endl; };
};
int main()
{
vector<tClass*> MyClass(5);
cout << MyClass[3]->y << endl;
}
note though that this will give an error as the vector of class pointers are not pointing to any class

Error when call vector's size() for the class field

I stuck with the problem of checking size of an vector in the class. Here is my code:
class myclass {
public:
std::vector<mystruct> v;
};
int main() {
myclass * a, *b;
std::cout << a->v.size() << '\n';
return 0;
}
This code gets segmentation fault. Would someone explain what is the mistake in this snippet? And how could I beat it?
You haven't allocated any memory for the pointers; your program behaviour is therefore undefined.
Why not use local automatic variables? myclass a, b; will suffice. You'll also need to replace the pointer to member operator -> with the member selection operator ..
You want to do:
int main() {
myclass a, b;
std::cout << a.v.size() << '\n';
return 0;
}
In your code, you are using two pointers to myclass objects, but they are not initialized, so when you dereference a through the arrow operator, you invoke undefined behavior.

How can RAII be used with pointers?

If have a class:
class classA {
public:
int z = 5;
};
I understand RAII to be when I write classA Aobject but what do I do if I want to declare a global pointer?
classA *Aobject;
int main()
{
Aobject = new classA; //not RAII
cout << Aobject->z << endl;
return 1;
}
I assume that what you mean is you want to declare an object, but you don't want to initialize it right away, perhaps because you don't have all the parameters you need in order to construct it properly yet. Is that correct? Use a smart pointer.
#include <memory>
#include <iostream>
std::unique_ptr<classA> Aobject;
int main()
{
Aobject.reset(new classA);
cout << Aobject->z << endl;
return 1;
}

Why aren't these shared_ptrs pointing to the same container?

I have a class Model:
class Model
{
...
boost::shared_ptr<Deck> _deck;
boost::shared_ptr<CardStack> _stack[22];
};
Deck inherits from CardStack.
I tried to make _stack[0] point to the same thing that _deck points to by going:
{
_deck = boost::shared_ptr<Deck>(new Deck());
_stack[0] = _deck;
}
It seems that the assignment to _deck of _stack[0] results in a copy of _deck being made. (I know this because modifications to _stack[0] do not result in modifications to _deck.) How can I get them to point to the same thing?
Ok - no copy constructor is being called. I have verified this by implementing it and seeing if it gets called - it doesn't.
However - I have a function that operates on CardStack objects:
void TransferSingleCard(CardStack & src, CardStack & dst, Face f)
{
if( !src._cards.empty() )
{
src._cards.back().SetFace(f);
dst.PushCard(src._cards.back());
src._cards.pop_back();
}
}
Now - when I call:
{
TransferSingleCard(*_stack[DECK], _someotherplace, FACEDOWN);
std::cout << *_stack[DECK];
std::cout << *_deck;
}
I get this output (where std::cout on a CardStack will print out the size of that stack):
Num(103) TOP
Num(104) TOP
... so I've concluded (incorrectly?) that _stack[DECK] points to something different.
The Deck
class Deck : public CardStack
{
public:
Deck(int numsuits=2, StackIndex index = NO_SUCH_STACK );
Deck::Deck( const Deck & d);
int DealsLeft() const;
void RecalcDealsLeft();
private:
int _dealsleft;
};
Not clear what you are asking about - consider this code:
#include <iostream>
#include "boost/shared_ptr.hpp"
using namespace std;
struct A {
virtual ~A() {
cout << "destroyed" << endl;
}
};
struct B : public A {
};
int main() {
boost::shared_ptr<B> b( new B );
boost::shared_ptr<A> a;
a = b;
}
Only one "destroy" message appears, indicating that no copy has been made.
This example - derives from #Neil's answer, tries to emulate what you say is happening. Could you check that it works as expected (A and B have the same count) on your system.
Then we could try and modify this code or your code until they match.
#include <boost/shared_ptr.hpp>
#include <iostream>
class A {
public:
virtual ~A()
{
std::cerr << "Delete A" << std::endl;
}
int _count;
void decrement()
{
_count --;
}
};
class B : public A {
public:
virtual ~B()
{
std::cerr << "Delete B" << std::endl;
}
};
int main()
{
boost::shared_ptr<B> b(new B);
b->_count = 104;
boost::shared_ptr<A> a;
a = b;
a->decrement();
std::cerr << "A:" << a->_count << std::endl;
std::cerr << "B:" << b->_count << std::endl;
return 0;
}
EDIT:
So from the comment, we know the original pointers are correct, so now we need to trace.
Either:
log pointers to see when they change.
Use watchpoints in a debugger to see when the pointer changes.
Use a third shared pointer to see which pointer is changed.
Introduce a function that changes both pointers at the same time.
I think the problem is that you're assigning between different types here. boost::shared_ptr is a template and templates are not polymorphic even if the type in them is. So what's happening is that your compiler sees the assignment from boost::shared_ptr<Deck> to boost::shared_ptr<CardStack> and notices that it can make the assignment by calling the copy constructor for CardStack to duplicate the Deck object.
I think what you want the assignment to look like is something like this:
_stack[0] = boost::static_pointer_cast<CardStack>(_deck);
Which will do the conversion the way you expect it to.
I think you may want shared_array for _stack . . . Take a look at the documentation on shared_ptr;from boost.org, specifically:
http://www.boost.org/doc/libs/1_42_0/libs/smart_ptr/shared_ptr.htm
"Normally, a shared_ptr cannot
correctly hold a pointer to a
dynamically allocated array. See
shared_array for that usage."
Also, be aware of the T* get() function (not to be used without good reason) which returns the raw pointer being held by the managed pointer (shared_ptr in this case).