Hi I have a class which includes an array, I'm not passing this through my class constuctor (could be going wrong here?) The array is just defined in the class then initialized in a read method.
But in the main I make an instance of the class like:
myClass myClass1;
Then do:
myClass1 = myClass2;
Now I use a bubble sort method on the first class instance like:
MyClass1.sort();
Now when I write both of these instances out to text after the sort they are both sorted?
I have had a read into shallow and deep copys, but I can't understand why a method called after the shallow copy, would result in both of them being sorted? Is this expected behavoir?
a little more information:
In my class I just define the array as:
static string myArray[5];
then in a write method I write the 5 elements to it, is there a better way of doing this, I have to use a method to intialize it though.
How is your array defined/created? If you create it with new and reference it with a pointer, you'll need a custom copy constructor creating a deep copy (i.e. creating a new instance of the array and copying its contents). The default copy constructor will only do a shallow copy, so both instances would use the same memory (i.e. both pointers' point to the same array on the heap).
This will work with the default copy constructor:
class myclass {
char text[256];
}
This won't work with the default copy constructor (at least not as expected):
class myclass {
char *text;
myclass() : text(new char[256]) {}
~myclass() { delete [] text; }
}
A member defined as static will never be copied. All instances share it without further code required:
class myclass {
static char text[256];
}
A copy constructor for the second case could look like this (note this is simplified and not checking for valid values and such):
myclass(const myclass &base) : text(new char[256]) { strcpy(text, base.text); }
General rule of thumb:
Do I use any pointer member that is assigned the return value of some new? If so, write a copy constructor. If not, hen use he default one (unless you've got other reasons).
In my class I just define the array as:
static string myArray[5];
Should I declare it in the header, as its only declared in the cpp file? As its still copying both.
If you declare that outside of a class definition it will be a global variable. There will only be one instance of it. You need to declare it inside the class, and not static:
class MyClass1 {
// other things...
string myArray[5];
};
In any case, this kind of basic question is better answered by consulting a good C++ introductory book.
Related
So if I have something like the following:
class MyClass{
public:
MyClass(){
// do other stuff
*oc = OtherClass(params);
}
private:
OtherClass* oc;
}
When is a constructor called on OtherClass? Would its default be called once as soon as the MyClass initialization begins, and then be redefined with its value constructor during the MyClass constructor? Or does it just not exist during "//do other stuff". What if no default constructor is provided for other class, only a value? Would it be good practice to construct it where it is defined as a member variable?
A default constructor is one that can be called without parameters. For example this is a default constructor:
struct foo {
foo(){} // (should not actually be user defined)
};
This is also a default constructor:
struct bar {
bar(int x = 42) {}
};
In your code it might be that the constructor that is called is a default constructor, but it does not matter for your code, because you do pass a parameter.
When is a constructor called on OtherClass?
In the line *oc = OtherClass(params);.
Would its default be called once as soon as the MyClass initialization begins, and then be redefined with its value constructor during the MyClass constructor?
If you do not provide an initializer members are default initialized. Confusingly for a pointer this means it is not initialized.
Or does it just not exist during "//do other stuff".
The member does exist before, but its value is indeterminate. You cannot use the value without invoking undefined behavior.
What if no default constructor is provided for other class, only a value?
See above. The existance of a default constructor of OtherClass is not relavant here. It would be relevant if the member was OtherClass and not a pointer, because for members of class type default initialization calls the default constructor.
Would it be good practice to construct it where it is defined as a member variable?
It is good practice to provide an initializer for members rather than assign in the constructor:
class MyClass{
public:
MyClass() : oc(params) {
}
private:
OtherClass oc;
}
I replaced the member with an instance rather than a pointer, because using a raw pointer as member opens up a can of worms that would require an even longer answer. For more on that read What is The Rule of Three?. Note that when the member is not a pointer but a OtherClass then suddenly it matters if OtherClass has a default constructor, because if you do not provide an initializer, then the member will be default constructed. Though in the above I used the member initializer list and the member will be initialized by the constructor that takes one parameter.
ÓtherClass *oc; is a pointer and as such has no constructor. It has to be initialized to a valid object before you can dereference it.
You can ensure oc is initialized by, well, initializing it:
MyClass() : oc(new OtherClass()) {
...
*oc = OtherClass(params);
}
This will create a dummy oc when the class it created and then copy or move assign the real object to *oc later. This is wasteful, so why not initialize it with the final value directly:
MyClass() : oc(new OtherClass(params)) {
...
}
or if you have to compute params first:
MyClass : oc(nullptr) {
...
oc = new OtherClass(params);
}
Initializing oc with nullptr first isn't required but it is dirt cheap and it ensures accidentally using oc will access a nullptr and fail instead of oc being some random value that might not crash.
You can also, and better, ensure initialization by inlineing that:
class MyClass {
...
private:
OtherClass *oc(nullptr);
}
With that the compiler will initialize oc whenever you don't initialize it in an initializer list in the constructor.
That said: Do you really need a pointer there? You need a destructor, copy/move constructors and aissgnment operators to handle the pointer directly. An Otherclass oc; would be much easier to deal with.
But if you do need a pointer then you should use a smart pointer to handle ownership for you. That means use std::unique_ptr or more likely std::shared_ptr for it. You might not even need anything past the constructor that way. But think about what it means for copy/move to have the pointer shared. Read about the rule of 0/3/5.
I have a long class with a lot of data members. I want to write a copy constructor for it. But, if I write my own copy constructor, I lose access to the default copy constructor.
I just want to repair a few pointers in my own copy constructor. So I want to have a shallow copy of the object which can be done by the default copy constructor.
Is there a possibility to access the default copy constructor when I have my own copy constructor?
Wrap the things you don't want to change in a struct, and derive (privately) from it. In your copy constructor, simply invoke the copy constructor of your base class.
No you cannot have both default and your own copy c-tor.
But there are two workarounds with this problem:
1 Enclose your pointers in some class with defined copy semantics
Example:
class A {
public:
private:
int trivial1;
int trivial2;
...
SomePointer nontrivialMember;
};
class SomePointer {
public:
SomePointer(const SomePointer&); // here the non trivial part of A copy semantics
int* nonTrivialMember;
};
2 Enclose the trivial parameters in some trivial structure
Example:
class A {
public:
A(const A& o) : data(o.data) {
// non trivial part
}
private:
struct Data {
int trivial1;
int trivial2;
...
} data;
int* nontrivialMember;
};
I would always select the first solution.
[UPDATE]
There is also 3rd solution, very similar to my second, enclose your trivial part in privately inherited base class. I'd still prefer the 1st solution.
The simplest approach to this would be to wrap up the pointers into classes that will perform the 'repair' manually in their copy constructor, then you can happily use the default copy constructor.
No, there is no way to call the default copy constructor from an user defined copy constructor.
You can either use the default or your own, not both. If you want to choose different functionality for different objects you should just write a member function that handles that case.
void DeepCopy(MyClass* rhs);
For example.
You cannot access default copy ctor if you created your own - compiler just doesn't generate it. But ther is workaround - split you class into data structure and logic.
See example:
struct Data
{
int i;
std::string s;
Data(): i(), s() {}
};
class Code: private Data
{
public:
Code() {}
Code(const Code& rhs): Data(rhs) // Call default copy ctor
{
i = 42; // Your copy part
return *this;
}
};
My solution is a simple memcpy() instead of the impossible call to the implicit (compiler generated) copy constructor, as the example shown below:
Class Foo
{
public:
...
Foo (Foo & other) {
// copies trivial part (and non-trivial part with possible wrong values)
memcpy(this, &other, sizeof(Foo));
// your non-trivial part here, overwrites the wrong values (if any) above.
}
}
Yet the side-effect is that the memcpy() will also copy those non-trivial part, which is a waste. If the non-trivial part does not contain too much space, I will prefer my solution.
For example, a class like below wastes only 4 byte copy of the one pointer, assuming the size of a pointer is 4 bytes.
Class Bar
{
int x, y, z;
// memcpy() wastes these 4 bytes copy,
// since actual copy constructor wants a new string
string *s;
}
This worked for me... (C++11, don't know if it works on older std)
Not sure why it doesn't end up in an endless loop.
class Foo {
public:
Foo(const Foo &orig) {
*this = orig;
... exchange pointers, do own stuff
}
I try to replicate C++ destructors and constructors in my c programming. That means for every object or struct there is an initialization function and a destruct function which frees all of the objects resources like so:
struct MyObject {
struct string a;
struct string b;
struct string c;
};
ConstructMyObject(struct MyObject *obj) {
ConstructString(&obj->a);
ConstructString(&obj->b);
ConstructString(&obj->c);
}
DestructMyObject(struct MyObject *obj) {
DestructString(&obj->a);
DestructString(&obj->b);
DestructString(&obj->c);
}
The destruct function is called at the end of every function scope just like in c++ only that i put it manually there. So now in DestructMyObject function I call the destructors of every struct string type because for the struct string object i would also have a destruct function written just like for the struct MyObject Object.
Example with my problem:
int main {
struct MyObject Object1;
ConstructMyObject(&Object1);
...
...
...
TransferOwnershipFunction(Object1.b); /*takes a struct string object as argument*/
...
...
...
DestructMyObject(&Object1);
return 0;
}
You see that i have transfered ownership of one Member of Object1 to another function but everything of Object1 will be destroyed by its destructor in the main function.
How do c++ destructors handle this kind of situation? I don't want that the destructor for struct string b is called at the end of main but it will be called because i call the destructor for MyObject. The function TransferOwnershipFunction(...) is now responsible for freeing the string object.
EDIT
Somebody knows how a rust compiler would resolve this issue? So in Rust would i need to clone the struct string object I'm passing to TransferOwnershipFunction or is there another way of doing it because cloning (or copying i guees) seems to be a very expensive operation.
From my point of view main() should be responsible for creating and deleting of Object1. And TransferOwnershipFunction() should work with a copy of Object1.b. In this case:
You need to create functions which work as analog of copy constructor and assignment operator (for C++03). Also move constructor and move assignment operator were added in C++11.
In C++03 copy constructor and assignment operator are generated implicitly if you don't declare them. By default they copy objects by member of class (not by bytes in memory) using copy constructor of each member (except simple types like int, double...). So you need to imitate of passing Object1.b by value with calling of copy constructor: in TransferOwnershipFunction create new object of type struct string, copy content of it by member. If struct string contains a raw pointer as member and you call malloc for this member in struct string's constructor and free in destructor than in copy constructor of struct string you need to call malloc than copy all content from passed variable. Don't forget to call destructor at the end of TransferOwnershipFunction.
According to RAII you need to call destructors in reverse order relation to order of creating objects (order of constructors).
My assignment requires me to create a stack template class. My program is working fine, I was just wondering if its necessary in this case to define the constructor since its only member is a vector. This is the code:
#include<iostream>
#include<vector>
using namespace std;
template <class T>
class Stack{
public:
Stack(){}
void push(const T &item){
data.push_back(item);
}
void pop(){
data.pop_back();
}
bool isEmpty(){
return data.empty();
}
T getTop(){
top = data.back();
return(top);
}
private:
vector<T> data;
T top;
};
If so, would I also need to include a copy constructor? How do I implement either if the only member is a vector?
correction: i also have another member, if you have noticed. Question still stands, though.
If you do not care about initializing top during the construction, then you do can do any of the following three:
Stack(){};
or
Stack(): default;
or not declaring a constructor
However, not declaring is a bad practice and it will create problems if you are using a copy constructor or any other constructor with parameters.
For instance, if you created the constructor:
Stack(T i) { top = i; data.push_back(i); };
without having declared a constructor,
Stack<int>();
would generate a compiler error.
Just make sure that you set the value of top when push function is called (i.e. compare the new element with the current top every time you push, but if data.size() == 1 you should set this as a top without comparing, as top is undefined).
You don't need to declare a default constructor, compiler will generate one for you - unless class T hasn't defined one, on which case you might get an error.
You don't need a copy constructor also, for the same reasons, given the same premises - on this case, class T must have one.
You'll find detailed info on references below.
That been said, I see no reason for the extra "top" member, except for some sort of speed optimization.
References:
Default constructors - cppreference.com
Copy constructors - cppreference.com
First of all, there is no need to define constructor and copy constructor.
If we do not define a constructor and copy constructor, the compiler will synthesizes one, and the synthesized constructor will help us to initialize class member variable. You does not need to initialize any member variable with a special value in your class.
How to define copy control? From C++ Primer: "There are three basic operations to control copies of class objects: the copy constructor, copy-assignment operator, and destructor."
Classes That Need Destructors Need Copy and Assignment: One rule of thumb to use when you decide whether a class needs to define its own versions of the copy-control members is to decide first whether the class needs a destructor. Often, the need for a destructor is more obvious than the need for the copy constructor or assignment operator. If the class needs a destructor, it almost
surely needs a copy constructor and copy-assignment operator as well.
Example:
class Int
{
public:
Int(int vValue = 0) : m_Pointer(new int(vValue)) {}
~Int()
{
delete m_Pointer;
m_Pointer = NULL;
}
private:
int* m_Pointer;
};
We defined an int Wrapper Class like JAVA. This class allocates dynamic memory in its constructor, The synthesized destructor will not delete a data member that is a pointer. Therefore, this class needs to define a destructor to free the memory allocated by its constructor.
Unfortunately, we have introduced a serious bug! This version of the class uses the synthesized versions of copy and assignment. Those functions copy the pointer member, just only copy the address where the pointer member points to:
Int(const Int& vInt)
{
m_Pointer = vInt.m_Pointer;
}
So, you must define your own copy constructor and assignment operator to control the memory assignment.
Short version: Can I safely create a copy constructor for a class that has member pointer variables, one of which is on the heap, that are of type xercesc::XercesDOMParser* and xercesc::DOMDocument*? If so, how?
Long version:
I wrote a class to wrap a Xercesc document object. It has two member variables that are pointers to a XercesDOMParser and a DOMDocument. Here is the part of the class declaration that shows those two members:
class XMLigator {
private:
xercesc::XercesDOMParser* _pParser;
xercesc::DOMDocument* _pDocument;
etc...
The pointers _pParser and _pDocument are initialized in the constructor. Here is an abbreviated version of the constructor with the relevant code. Notice that _pParser is created with the new operator and is on the heap:
XMLigator::XMLigator(string strFile) : _strFile(strFile), _pDocument(NULL) {
xercesc::XMLPlatformUtils::Initialize();
_pParser = new xercesc::XercesDOMParser();
_pParser->parse(_strFile.c_str());
_pDocument = _pParser->getDocument();
}
The destructor deletes the member variable _pParser:
XMLigator::~XMLigator(void) {
if (m_pParser) {
delete _pParser;
}
}
Until now I have prohibited the copy constructor and assignment operator by marking them private and not defining them.
Now I would like to, if possible, create a copy constructor for this class so I can make it a return type for a function, in this fashion:
XMLigator getOne() {
XMLigator xml("/some/file.xml");
return xml;
}
The first problem I see is my the destructor does a delete _pParser;. So I think that's a problem. I am pretty sure I have to remove the delete from the destructor. But then I have a memory leak.
I really have no idea how to approach this. Maybe it's not possible. Does anyone have an approach that I can use for this?