I'm writing an application, where I want to store strings as keys ans a custom Object as value
multimap<string, owncreatedobject> mymap;
Compiling does well, but I get a "Segmentation fault" when using the function insert
during runtime.
mymap.insert(string,myobject); --> Segmentation Error
A already added a copyconstructor an assignmentfunction (which calls the copyconstructor)
any idea about the "Segmentation fault?
Looking at the comment you added for the copy constructor and assignment operator implementation, I found that your assignment operator implementation is wrong. Basically it is not copying anything, instead with the statement Filter(f); , you are creating a local object named f. You can not call copy constructor like that. I suggest you to write a private copy method and use it in both copy ctor and assignment operator.
I fiddle with your problem for the last hour and I think I got it.
Try using something in the matter of this code segment:
multimap<string,yourclass const*> mymap
void addtomap(string s,yourclass const* c)
{
mymap.insert(pair<string, yourclass const*>(s,c));
}
...`addtomap("abc",&z);
In your given example you tried to insert without an iterator. The first element for a 2 element insert call for a multimap is the iterator. That's the reason for your segmentation fault and why one should use pair.
I suspect that you have a buggy copy constructor and/or assignment operator implementation.
If the line
mymap.insert(std::make_pair(mystring,myobject));
crashes, it's pretty likely that some method which is executed on 'myobject' causes the problem. In this code line, the most interesting functions are the copy constructor and/or the assignment operator.
You say that you already added an assignment operator (which calls the copy constructor), but that sounds strange. Usually it's exactly the other way round; the copy constructor allocates resources (i.e. memory) as needed and then calls the assignment operator.
UPDATE: After reading your comment, here's how your copy constructor should look like:
Filter::Filter( const Filter &rhs ) {
// Apparently no resource acquisition like memory allocation is necessary,
// so just assign the rhs value.
*this = rhs;
}
And here's the assignment operator. Note how it just copies over the values. Chances are that you don't need an assignment operator (or copy constructor) implementation at all because the compiler-synthesized code is fine for your uses.
Filter &Filter::operator=( const Filter &rhs ) {
SrcNET = f.SrcNET;
SrcPort = f.SrcPort;
DstNET = f.DstNET;
FlowLabel = f.FlowLabel;
return *this;
}
I assume you're trying to call the insert version that accepts a value_type of the multimap. In this case, just remember that multimap's value_type is a std::pair. Then, try this:
mymap.insert(std::make_pair(mystring,myobject));
EDIT (after your comment): Your assignment operator contains an error. You create a temporary that serves for no purpose. Below is a suggestion of implementation using the swap idiom. (Notice that I don't know what are the types of the class member. Suppose they're a builtin such as int for example.)
void Swap(Filter const& f) //Create a swap member function.
{
std::swap(SrcNET, f.SrcNET);
std::swap(SrcPort, f.SrcPort);
std::swap(DstNET, f.DstNET);
std::swap(DstPort, f.DstPort);
std::swap(FlowLabel, f.FlowLabel);
}
Filter& Filter::operator =(Filter f)
{
swap(f); //Swaps the copy created for parameter passing (pass-by-value) above.
return *this;
}
Related
Title kind of hits the mark.
// copy constructor
IntList::IntList(const IntList& source){
Node* currentNode = source.first;
first = nullptr;
while(currentNode){
append(currentNode->info);
currentNode = currentNode->next;
}
}
//Assignment operator should copy the list from the source
//to this list, deleting/replacing any existing nodes
IntList& IntList::operator=(const IntList& source){
this -> ~IntList();
this = new IntList(source);
return *this;
}
Error:
intlist.cpp:26:30: error: lvalue required as left operand of assignment
this = new IntList(source);
The destructor properly deletes each node in the linked list. Technically "this" would be whatever linked list was passed in with the assignment operator. Isn't that treated as an object that can be set?
The short answer is that you can't assign this. (this is the pointer to the current object it cannot be "relocated", it is a "const" pointer for all purposes).
What you mean is something like:
new(this) IntList(source);
Which is called "placement" new:
But you don't need to learn about this because all this is bad anyway. Keep reading...
Yours is an old and bad design pattern to implement assignment as destruction + construction.
These days, unless there is a better shortcut (that depends on you specific design) we implement swap (also useful) and then operator= from copy(construct)+swap.
(Besides any explict call to the destructor smells bad.)
IntList& IntList::operator=(IntList const& source){
IntList tmp(source)
this->swap(tmp);
return *this;
}
The main point is not only more elegant code, ultimately a side effect is that you are writing exception safe code by default. (think of what happens if the new object cannot be constructed in your original code: the *this object is left in an invalid "destructed" state.)
See the series of talks: https://www.youtube.com/watch?v=W7fIy_54y-w
This is really advanced now and it gets weird (as discussed with #PaulMcKenzie).
It turns out that (I think for some quirks only in C++14), that you can omit the temporary and transfer that into the argument itself passed by value:
IntList& IntList::operator=(IntList source) noexcept{
return swap(source);
}
Although it can be obscure at first.
It is less code
it is noexcept: it can't fail!. The operation call can fail but not inside the function
this provides move assignment if there a move constructor, so you don't need to write a separate move assignment (even less code).
(Incidentally, I think this shows why member swap should return *this)
This opens an intriguing question: if I have copy constructor and swap, shouldn't the compiler implement operator= automatically for me? (not the old-C operator= member-by-member, but one that knows about the semantics of the class implemented like shown). IntList& operator=(IntList) = default;
Finally, don't miss the forest for the tree.
You wanted to implement assignment without writing new code, assuming that your copy constructor was good and that is all you got.
However this is still not always optimal!
For containers copy construction usually involves a) (unconditional) allocation and b) a sequence of "uninitialized copies" (ultimately a form of placement new).
Both a) and b) are slower than A) no-allocation and B) a sequence of assignment respectively.
This means that, if for some reason you know that you don't need to allocate (e.g. because the source "fits" in your allocated memory already), and that you can assign element by element (faster than new-place element by element) you might be in good shape to get a more optimal solution by writing a custom operator= that takes into account all this.
If your copy constructor and destructor for IntList are working properly, the easiest way to implement the assignment operator is to use the copy/swap idiom:
#include <algorithm>
//...
IntList& IntList::operator=(const IntList& source)
{
if (&source != this)
{
IntList temp(source);
std::swap(temp.first, first);
// add swaps for each member
//...
} // <-- This is where the old contents will be destroyed,
// when `temp` goes out of scope. No need for this->~IntList();
return *this;
}
In your code, doing this:
this->~IntList();
is not necessary, and probably is wrong anyway. Code like that is reserved for usage with placement-new, and your code doesn't show any usage of placement-new.
A common mistake is to call the assignment operator from the copy constructor. Take the Array class for example. Inside the copy you might think it's simple to write
In this piece of code below, I am having std::map in a structure. And I am then just assigning an instance of the structure to other. Note that the structure doesn't have assignment operator. In this case shall I expect assignment operator of map would be called or compiler just shallow copies memory contains of structures ?
int _tmain(int argc, _TCHAR* argv[])
{
struct vectstruct
{
std::map<int, double> mymap;
};
vectstruct vs1, vs2;
vs1.mymap[7] = 54.321;
vs2 = vs1; // Should call assignment operator of map vs2.mymap
vs1.mymap[7] = 65.432;
return 0;
}
I tried this with Microsft Visual Studio and at the end of program I see value of vs2.mymap[7] remains 54.321 as expected. But I like to know is it correct by C++ standards or do I need to write assignment operator of vectstruct wherein I explicitly would invoke assignment operator of map?
As a matter of style, you should declare and define your types outside of main.
That said, if you do not provide a copy assignment operator, the compiler will implicitly create* one for you and that implicit one will just do an element-wise copy assignment. In this case, the implicit one will look something like:
vectstruct& operator=(const vectstruct& rhs) {
mymap = rhs.mymap;
return *this;
}
For std::map, assignment does full copy, it doesn't take a reference, so at the end of your code you should expect:
vs2.mymap[7] == 54.321 // to the extent that equality of doubles is a thing
vs1.mymap[7] == 65.432
*There are cases when the compiler cannot create an implicit assignment operator which basically boil down to your object having a noncopyable member. For instance, a reference, or a unique_ptr.
The default operator= will perform a member-by-member copy, which is what you expect. I. e. it will invoke operator= for every data member of your struct. And std::map, in turn, implements operator=, so everything will work like charm. No need to bloat your code by writing the same operator yourself.
I'm getting a segmentation fault which I believe is caused by the copy constructor. However, I can't find an example like this one anywhere online. I've read about shallow copy and deep copy but I'm not sure which category this copy would fall under. Anyone know?
MyObject::MyObject{
lots of things including const and structs, but no pointers
}
MyObject::MyObject( const MyObject& oCopy){
*this = oCopy;//is this deep or shallow?
}
const MyObject& MyObject::operator=(const MyObject& oRhs){
if( this != oRhs ){
members = oRhs.members;
.....//there is a lot of members
}
return *this;
}
MyObject::~MyObject(){
//there is nothing here
}
Code:
const MyObject * mpoOriginal;//this gets initialized in the constructor
int Main(){
mpoOriginal = new MyObject();
return DoSomething();
}
bool DoSomething(){
MyObject *poCopied = new MyObject(*mpoOriginal);//the copy
//lots of stuff going on
delete poCopied;//this causes the crash - can't step into using GDB
return true;
}
EDIT: Added operator= and constructor
SOLVED: Barking up the wrong tree, it ended up being a function calling delete twice on the same object
It is generally a bad idea to use the assignment operator like this in the copy constructor. This will default-construct all the members and then assign over them. It is much better to either just rely on the implicitly-generated copy constructor, or use the member initializer list to copy those members that need copying, and apply the appropriate initialization to the others.
Without details of the class members, it is hard to judge what is causing your segfault.
According to your code you're not creating the original object... you're just creating a pointer like this:
const MyObject * mpoOriginal;
So the copy is using bad data into the created new object...
Wow....
MyObject::MyObject( const MyObject& oCopy)
{
*this = oCopy;//is this deep or shallow?
}
It is neither. It is a call to the assignment operator.
Since you have not finished the construction of the object this is probably ill-advised (though perfectly valid). It is more traditional to define the assignment operator in terms of the copy constructor though (see copy and swap idium).
const MyObject& MyObject::operator=(const MyObject& oRhs)
{
if( this != oRhs ){
members = oRhs.members;
.....//there is a lot of members
}
return *this;
}
Basically fine, though normally the result of assignment is not cont.
But if you do it this way you need to divide up your processing a bit to make it exception safe. It should look more like this:
const MyObject& MyObject::operator=(const MyObject& oRhs)
{
if( this == oRhs )
{
return *this;
}
// Stage 1:
// Copy all members of oRhs that can throw during copy into temporaries.
// That way if they do throw you have not destroyed this obbject.
// Stage 2:
// Copy anything that can **not** throw from oRhs into this object
// Use swap on the temporaries to copy them into the object in an exception sage mannor.
// Stage 3:
// Free any resources.
return *this;
}
Of course there is a simpler way of doing this using copy and swap idum:
MyObject& MyObject::operator=(MyObject oRhs) // use pass by value to get copy
{
this.swap(oRhs);
return *this;
}
void MyObject::swap(MyObject& oRhs) throws()
{
// Call swap on each member.
return *this;
}
If there is nothing to do in the destructor don't declare it (unless it needs to be virtual).
MyObject::~MyObject(){
//there is nothing here
}
Here you are declaring a pointer (not an object) so the constructor is not called (as pointers don;t have constructors).
const MyObject * mpoOriginal;//this gets initialized in the constructor
Here you are calling new to create the object.
Are you sure you want to do this? A dynamically allocated object must be destroyed; ostensibly via delete, but more usually in C++ you wrap pointers inside a smart pointer to make sure the owner correctly and automatically destroys the object.
int main()
{ //^^^^ Note main() has a lower case m
mpoOriginal = new MyObject();
return DoSomething();
}
But since you probably don't want a dynamic object. What you want is automatic object that is destroyed when it goes out of scope. Also you probably should not be using a global variable (pass it as a parameter otherwise your code is working using the side affects that are associated with global state).
int main()
{
const MyObject mpoOriginal;
return DoSomething(mpoOriginal);
}
You do not need to call new to make a copy just create an object (passing the object you want to copy).
bool DoSomething(MyObject const& data)
{
MyObject poCopied (data); //the copy
//lots of stuff going on
// No need to delete.
// delete poCopied;//this causes the crash - can't step into using GDB
// When it goes out of scope it is auto destroyed (as it is automatic).
return true;
}
What you are doing is making your copy constructor use the assignment operator (which you don't seem to have defined). Frankly I'm surprised it compiles, but because you haven't shown all your code maybe it does.
Write you copy constructor in the normal way, and then see if you still get the same problem. If it's true what you say about 'lots of things ... but I don't see any pointers' then you should not be writing a copy constructor at all. Try just deleting it.
I don't have a direct answer as for what exactly causes the segfault, but conventional wisdom here is to follow the rule of three, i.e. when you find yourself needing any of copy constructor, assignment operator, or a destructor, you better implement all three of them (c++0x adds move semantics, which makes it "rule of four"?).
Then, it's usually the other way around - the copy assignment operator is implemented in terms of copy constructor - copy and swap idiom.
MyObject::MyObject{
lots of things including const and structs, but no pointers
}
The difference between a shallow copy and a deep copy is only meaningful if there is a pointer to dynamic memory. If any of those member structs isn't doing a deep copy of it's pointer, then you'll have to work around that (how depends on the struct). However, if all members either don't contain pointers, or correctly do deep copies of their pointers, then the copy constructor/assignment is not the source of your problems.
It's either, depending on what your operator= does. That's where the magic happens; the copy constructor is merely invoking it.
If you didn't define an operator= yourself, then the compiler synthesised one for you, and it is performing a shallow copy.
I searched how to implement + operator properly all over the internet and all the results i found do the following steps :
const MyClass MyClass::operator+(const MyClass &other) const
{
MyClass result = *this; // Make a copy of myself. Same as MyClass result(*this);
result += other; // Use += to add other to the copy.
return result; // All done!
}
I have few questions about this "process" :
Isn't that stupid to implement + operator this way, it calls the assignment operator(which copies the class) in the first line and then the copy constructor in the return (which also copies the class , due to the fact that the return is by value, so it destroys the first copy and creates a new one.. which is frankly not really smart ... )
When i write a=b+c, the b+c part creates a new copy of the class, then the 'a=' part copies the copy to himself.
who deletes the copy that b+c created ?
Is there a better way to implement + operator without coping the class twice, and also without any memory issues ?
thanks in advance
That's effectively not an assignment operator, but a copy constructor. An operation like addition creates a new value, after all, so it has to be created somewhere. This is more efficient than it seems, since the compiler is free to do Return Value Optimization, which means it can construct the value directly where it will next be used.
The result is declared as a local variable, and hence goes away with the function call - except if RVO (see above) is used, in which case it was never actually created in the function, but in the caller.
Not really; this method is much more efficient than it looks at first.
Under the circumstances, I'd probably consider something like:
MyClass MyClass::operator+(MyClass other) {
other += *this;
return other;
}
Dave Abrahams wrote an article a while back explaining how this works and why this kind of code is usually quite efficient even though it initially seems like it shouldn't be.
Edit (thank you MSalters): Yes, this does assume/depend upon the commutative property holding for MyClass. If a+b != b+a, then the original code is what you want (most of the same reasoning applies).
it calls the assignment operator(which copies the class) in the first line
No, this is copy-initialization (through constructor).
then the copy constructor in the return (which also copies the class
Compilers can (and typically do) elide this copy using NRVO.
When i write a=b+c, the b+c part creates a new copy of the class, then the 'a=' part copies the copy to himself. who deletes the copy that b+c created
The compiler, as any other temporary value. They are deleted at the end of full-expression (in this case, it means at or after ; at the end of line.
Is there a better way to implement + operator without coping the class twice, and also without any memory issues ?
Not really. It's not that inefficient.
This appears to be the correct way to implement operator+. A few points:
MyClass result = *this does not use the assignment operator, it should be calling the copy constructor, as if it were written MyClass result(*this).
The returned value when used in a = b + c is called a temporary, and the compiler is responsible for deleting it (which will probably happen at the end of the statement ie. the semicolon, after everything else has been done). You don't have to worry about that, the compiler will always clean up temporaries.
There's no better way, you need the copy. The compiler, however, is allowed to optimise away the temporary copies, so not as many as you think may be made. In C++0x though, you can use move constructors to improve performance by transfering ownership of the content of a temporary rather than copying it in its entirity.
I'll try my best to answer:
Point (1): No, it does not call the assignment operator. Instead it calls a constructor. Since you need to construct the object anyway (since operator+ returns a copy), this does not introduce extra operations.
Point (2): The temporary result is created in stack and hence does not introduce memory problem (it is destroyed when function exits). On return, a temporary is created so that an assignment (or copy constructor) can be used to assign the results to a (in a=b+c;) even after result is destroyed. This temporary is destroyed automatically by the compiler.
Point (3): The above is what the standard prescribes. Remember that compiler implementors are allowed to optimize the implementation as long as the effect is the same as what the standard prescribed. I believe, compilers in reality optimize away many of the copying that occurs here. Using the idiom above is readable and is not actually inefficient.
P.S. I sometime prefer to implement operator+ as a non-member to leverage implicit conversion for both sides of the operators (only if it makes sense).
There are no memory issues (provided that the assignment operator, and copy constructor are well written). Simply because all the memory for these objects is taken on the stack and managed by the compiler. Furthermore, compilers do optimize this and perform all the operations directly on the final a instead of copying twice.
This is the proper way of implementing the operator+ in C++. Most of the copies you are so afraid of will get elided by the compiler and will be subject to move semantics in C++0x.
The class is a temporary and will be deleted. If you bind the temporary to a const& the life time of the temporary will be extended to the life time of the const reference.
May implementing it as a freefunction is a little more obvious. The first parameter in MyClass::operator+ is an implicit this and the compiler will rewrite the function to operator+(const MyClass&, const MyClass&) anyway.
As far as I remember, Stroustrup's 'The C++ Programming Language' recommends to implement operators as member functions only when internal representation is affected by operation and as external functions when not. operator+ does not need to access internal representation if implemented based on operator+=, which does.
So you would have:
class MyClass
{
public:
MyClass& operator+=(const MyClass &other)
{
// Implementation
return *this;
}
};
MyClass operator+(const MyClass &op1, const MyClass &op2)
{
MyClass r = op1;
return r += op2;
}
ostream& operator<<(ostream& out, const hashmap& h)
{
const char *getSymbol = NULL;
h.hashTable->displayHeaders(out);
for ( int hashIndex = 0; hashIndex < maxSize; hashIndex++ )
{
getSymbol = h.hashTable[hashIndex].getSymbol();
if ( getSymbol )
{
out << h.hashTable[hashIndex];
}
}
return out;
}
If I read the code right as the formatting is somewhat off, the problem is most likely that your stock copy constructor does a shallow copy whereas the assignment operator for the same class makes a deep copy. From reading the rest of the code, I assume you meant to make a deep copy instead of just duplicating the m_name and m_symbol pointers.
I'd also strongly suggest that you use std::string instead of raw char pointers - doing that in the first place would have avoided the issues I describe above. It would've also allowed you to use the compiler generate copy constructor, assignment operator and destructor. Less code is good.
Something went wrong with the formatting when you posted your code, so I had to move it to an external editor to read.
The problem is not a memory leak - that would be memory that you failed to reclaim. This is quite the opposite issue. Here, you are trying to reclaim memory that was already freed.
I would bet anything that the failing delete call in the destructor is occuring on an object that was either copied or populated using either the copy constructor or the second overloaded assignment operator. You are performing a shallow copy in those places, resulting in two stock objects referencing exactly the same memory for their mname and msymbol members. Whichever one of the two (or more if you copied many times) is destroyed first will have no problems. Whichever one is destroyed second will fail.
I also make the following observation: your constructor carefully checks symbol and name to see if they actually reference any data. Only then do you proceed to use their values. If they are null, then you assign a value of null to the corresponding members. The first overloaded assignment operator, on the other hand, is copying an instance of stock that for all you know could have null mname or msymbol members. You should treat those values with the same care you did in the constructor and test them before using.
The problem is here:
stock& stock::operator=(stock const * const s)
Look at the logic of this operator and the other assignment operator you declared: you copy m_symbol and m_name differently!
You would be better off defining the assignment operator only once:
stock& stock::operator=(stock const * const s)
{
return this->operator=(*s);
}
Or the other way around if you prefer, but remember that the implementation of this one is off.