operators on Iterators in C++ - c++

I am porting an old code base to OSX.
I have the following snippet of code:
FxLayerList::iterator lastVisible = NULL;
for (FxLayerList::iterator iter = mBranch.begin(); iter != mBranch.end(); iter++) {
if ( (*iter)->IsVisible() && !(*iter)->IsBypass()) {
lastVisible = iter;
}
}
if (lastVisible != NULL && (*lastVisible)->GetGeneratedImage()) {
I get an error that says: error: no match for 'operator!=' in 'lastVisible != 0'
I dont follow, I thought operations like != and ==, etc were standard operations. Why the complaint from the compiler?
UPDATE: I am trying to understand the comparison of objects. What if the code is like this:
FxBool FxLayerList::Contains(FxLayer *layer) const
{
for (FxLayerList::const_iterator iter=this->begin(); iter != this->end(); iter++)
{
if ((*iter) == layer) {
return true;
}
}
return false;
}
with errors like: error: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second:
What is the core concept I am missing?
Update 2:
// FxSmartPtr is a smart pointer that is also typed for each class, avoiding the need for any casting.
// Setting an FxSmartPtr to NULL actually kills the memory that it's pointing to as well.
template <class eachClass>
class FxSmartPtr
{
public:
// Construction
// Default constructor makes an empty container.
FxSmartPtr(void) : mPtr(NULL) {}
// Construction with a ptr adds one reference to it.
FxSmartPtr(eachClass *ptr) : mPtr(ptr) { this->Reference(); }
// Copy construction means that both smart pointers end up with a reference to the object.
FxSmartPtr(const FxSmartPtr & inPtr) :mPtr(NULL) { FrAssignRef(mPtr,(eachClass *)inPtr.mPtr); }
// Default construction
FxSmartPtr(FxConstructArg cons) { if (cons == FcNew) mPtr = new eachClass(); }
FxSmartPtr(FxConstructArg cons,eachClass *ptr) { if (cons == FcNew) mPtr = ptr; }
// Destructor removes only the one reference that we own.
~FxSmartPtr() { this->Dispose(); }
// Most important and common use is via assignment. References are always safely balanced.
// AssignReference safely replaces one reference counted ptr with another.
static inline eachClass * FrAssignRef(eachClass *& to, eachClass * from)
{ if (from) from->AddReference(); if (to) to->RemoveReference(); to = from; return to; }
// If you assign a pointer to this object we add one reference count to it.
const FxSmartPtr<eachClass> & operator = (const eachClass *ptr)
{ FrAssignRef(mPtr,(eachClass *)ptr); return *this; }
// Replace our referenced object with a reference added to the incoming one.
const FxSmartPtr<eachClass> & operator = (const FxSmartPtr & inPtr)
{ FrAssignRef(mPtr,(eachClass *)inPtr.mPtr); return *this; }
// Assignment to a dumb pointer takes/gives no references.
operator eachClass * (void) const
{ return mPtr; }
eachClass * operator->(void)
{ if (mPtr != NULL) if (mPtr->GetRefCount() < 1 || mPtr->GetRefCount() > 10000) ASSERT(0); return mPtr; }
const eachClass * operator->(void) const
{ if (mPtr != NULL) if (mPtr->GetRefCount() < 1 || mPtr->GetRefCount() > 10000) ASSERT(0); return mPtr; }
// Explicit assignment and object transfers
// Get() - return ptr with no reference
eachClass * Get(void) const
{ return mPtr; }
eachClass * GetPtr(void)
{ return mPtr; }
// Own() - return ownership with ptr
eachClass * Own(void)
{ if (mPtr) mPtr->AddReference(); return mPtr; }
// Set() - we take our own reference on your object
FxSmartPtr<eachClass> & Set(eachClass * ptr)
{ FrAssignRef(mPtr, ptr); return *this; }
// Take() - you give us your reference
FxSmartPtr<eachClass> & Take(eachClass * ptr)
{ FrDispose(mPtr); mPtr = ptr; return *this; }
// Comparison operators compare the pointers contained in each
FxBool operator == (const FxSmartPtr & inPtr) const
{ return (mPtr == inPtr.mPtr); }
FxBool operator == (const eachClass * inPtr) const
{ return (mPtr == inPtr); }
FxBool operator != (const FxSmartPtr & inPtr) const
{ return (mPtr != inPtr.mPtr); }
FxBool operator != (const eachClass * inPtr) const
{ return (mPtr != inPtr); }
// Reference() and Dispose() change the normal reference count. If you use these then
// you end up having to count references externally.
// Safely take a reference if the ptr is not nil
void Reference(void) { if (mPtr != NULL) mPtr->AddReference(); }
// Safely dispose one reference count.
void Dispose(void) { if (mPtr != NULL)
// JASON/INDIE - SLACKMOEHRLE#GMAIL.COM
// { ULONG refs = mPtr->GetRefCount(); mPtr->RemoveReference(); if (refs <= 1) mPtr = NULL; } }
{ FxUInt32 refs = mPtr->GetRefCount(); mPtr->RemoveReference(); if (refs <= 1) mPtr = NULL; } }
protected:
eachClass *mPtr;
};

It looks that lastVisible is an object rather than just a pointer. If you compare some object with something, then it has to have the appropriate operator.
Maybe this would compile?
FxLayerList::iterator lastVisible = mBranch.end();
for (FxLayerList::iterator iter = mBranch.begin(); iter != mBranch.end(); iter++)
{
if ( (*iter)->IsVisible() && !(*iter)->IsBypass())
{
lastVisible = iter;
}
}
if (lastVisible != mBranch.end() && (*lastVisible)->GetGeneratedImage())
{ ...
Or if FxLayerList is just a collection of pointers to FxLayer, this would be more straightforward:
FxLayer *lastVisible = NULL;
for (FxLayerList::iterator iter = mBranch.begin(); iter != mBranch.end(); iter++)
{
if ( (*iter)->IsVisible() && !(*iter)->IsBypass())
{
lastVisible = *iter;
}
}
if (lastVisible != NULL && lastVisible->GetGeneratedImage())
{ ...
Answer to UPDATE: see my comment below. The problem (compiler error message) can be solved by explicitly retrieving the pointer from the "smart" pointer:
FxBool FxLayerList::Contains(FxLayer *layer) const
{
for (FxLayerList::const_iterator iter=this->begin(); iter != this->end(); iter++)
{
if (iter.Get() == layer) {
return true;
}
}
return false;
}

The standard operators are overloadable to support directly comparing objects, but out of the box they wouldn't know what to compare (I think the default behaviour would be to simply compare the object's address, but your error seems to contradict that).
In any event, How to compare two objects (the calling object and the parameter) in a class? seems to be a very similar problem.
Within your class you should probably add in something like what Alexander suggested above:
int Date :: Compare (const Date& d) {
if (year<d.year) {
return -1;
}
}
bool operator == (const Date& d) const {
return !Compare(d);
}
Of course modified to suit your comparison requirements.

Related

Array Wrapper Corrupts Heap

Sequel to: array wrapper corrupts stack
The project:
I am working on a std::vector replacement.
The error:
I get a heap corruption error whenever I attempt to delete a temporary array I am creating in order to store the copied elements of another array that I delete in order to reallocate it when my array gets resized. (It seems that if I try to assign one array to another, I actually end up assigning the pointer to the array to the other array instead of copying the elements. Truly crazy stuff).
I read online that this error may actually come from the part where I actually interact with the array, but the error only pops out when I attempt to delete it.
Where I interact with the array is the function _tempcpy. I pass a pointer to a source and destination array and copy each element from the source to the destination. I struggled a bit with making sure that the array would start from 0 and not 1 and in the process I messed a bit too much with the element_count member, so it may be that i am somehow writing outside of bounds and I have stared so much at the code I can't see the issue.
The code:
template<class T> class dyn_arr
{
public:
dyn_arr(void)
{
this->array = {};
this->element_count = {};
}
~dyn_arr(void)
{
this->dealloc();
}
bool alloc(unsigned int element_count)
{
if (0 == element_count)
{
element_count = 1;
}
if (this->array != nullptr)
{
T* temp = new T[this->element_count];
if (false == this->_tempcpy(&this->array, &temp, this->element_count))
{
return false;
}
delete[] this->array;
this->array = new T[this->element_count];
if (false == this->_tempcpy(&temp, &this->array, this->element_count))
{
return false;
}
delete[] temp;
if (nullptr != this->array)
{
return true;
}
}
else
{
this->array = new T[this->element_count];
if (nullptr != this->array)
{
return true;
}
}
return false;
}
bool dealloc(void)
{
if (nullptr == this->array)
{
return false;
}
delete[] this->array;
return true;
}
bool add(T Object)
{
if (0 == Object)
{
return false;
}
if (true == this->alloc(this->element_count))
{
this->array[this->element_count] = Object;
++this->element_count;
return true;
}
return false;
}
T get(unsigned int index)
{
if (index > this->element_count)
{
return T{};
}
return this->array[index];
}
unsigned int get_count(void)
{
return this->element_count;
}
private:
bool _tempcpy(T** src, T** dest, unsigned int count)
{
if ((nullptr == src) || (nullptr == dest) || (0 == count))
{
return false;
}
for (unsigned int i = 0; i < count; ++i)
{
*dest[i] = *src[i];
}
return true;
}
T* array;
unsigned int element_count;
};
int main()
{
dyn_arr<int> pNr = {};
pNr.add(1);
pNr.add(2);
pNr.add(3);
for (int i = 0; i < pNr.get_count(); ++i)
{
printf("%d\n", pNr.get(i));
}
getchar();
return 0;
}
In your alloc function there lie a few problems, such as:
if (0 == element_count)
{
element_count = 1;
}
is unnecessary. Instead, you can just do a +1 where necessary which is almost everywhere except the temp dynamic array.
bool alloc(...)
{
this->array = new T[this->element_count];
//...
else
{
this->array = new T[this->element_count];
}
}
should be
this->array = new T[this->element_count + 1];
//...
else
{
this->array = new T[this->element_count + 1];
}
this will fix the problems with allocation. That leaves us with _tempcpy() which fails because instead of trying to get the next element of the underlying array, it tries to do that with the double ptr itself. Read about operator precedence rules. Fixed version:
bool _tempcpy(T** src, T** dest, unsigned int count)
{
//....
for (unsigned int i = 0; i < count; ++i)
{
(*dest)[i] = (*src)[i];
}
//....
}
However, I am unsure as to why double ptr is needed in this function in the first place. Just use single pointers. Also dest should be const as it is not changing in this function. It gives the reader of the function a clear idea of which parameters will change inside the function and which will not:
bool _tempcpy(T* src, const T* dest, unsigned int count) {...}
same could be applied to other parts of the class.
Additionally, in C++
dyn_arr(void)
We don't do this. There's no need to explicitly write void. According to the C++ standard:
8.3.5 Functions [dcl.fct]
...
A parameter list consisting of a single unnamed parameter of non-dependent type void is equivalent to an empty parameter list.

Error reading character of string C++

I showed my codes and i have an error reading character of string. Everything is okey in my debugger until the NULL.
*Warning C4715 `String::equas`: not all control paths return a value*
I can not use it because I am using a NULL pointer for the parameter.
How can I solve this problem?
Thanks a lot and have a nice day!
Header:
class String
{
public:
String();
bool empty();
String(char * other_str);
bool equals(const String other_str);
private:
char* m_str;
};
My Codes:
#include "String.hpp"
#include <string>
#include<iostream>
int my_len(const char* p) {
int c = 0;
while (*p != '\0')
{
c++;
*p++;
}
return c;
}
String::String()
:m_str(NULL)
{
}
String::String(char * other_str)
{
}
bool String::empty()
{
return true;
}
bool String::equals(const String other_str)
{
if (m_str == NULL && other_str.m_str == NULL) {
return true;
}
if (m_str == NULL && other_str.m_str != NULL) {
return false;
}
if (m_str != NULL && other_str.m_str == NULL) {
return false;
}
if (m_str != NULL && other_str.m_str != NULL) {
int mystrlen = my_len(m_str);
int myrhslen = my_len(other_str.m_str);
if (mystrlen != myrhslen)
{
return false;
}
else
{
for (int i = 0; i < mystrlen; i++)
{
if (m_str[i] != other_str.m_str[i])
{
return false;
}
else {
return true;
}
}
}
}
}
i will add this codes:
int mylen(const char* p) {
int c = 0;
while (*p != '\0')
{
c++;
*p++;
}
return c;
}
void my_cpy(char dest, const char* src) {
int i = 0;
while (src[i] != '\0') {
dest[i] = src[i];
i++;
}
dest[i] = '\0';
}
char mytrdup(const char *s) {
char* d = (char*)malloc((my_len(s) + 1) * sizeof(char));
if (d == NULL) {
return NULL;
}
else{
my_cpy(d, s);
}
return d;
}
String empty_string2(NULL);
This will invokde the constructor version :
String::String(char* other_str) {}
which does nothing, leaving the m_str pointer dangling/uninitialized. You should change this constructor somehow, either by copying the string and setting the m_str pointer accordingly, or by setting m_str to the same address as the parameter. Either case it depends on what you want to achieve.
Besides, many other problems exist in your code. I notice already this one in you implemented function my_len. you should change *p++ into p++. I wonder how this passed the compilation btw, since the parameter is a const char*.
Finally, the compiler's warning is correct and very clear, although it is not the source of the problem you are facing for the time being.
EDIT: to make a duplicate copy of the string, you can write you constructor like this:
String::String(const char* other_str)
{ m_str = (other_str ? strdup(other_str) : other_str); }
And besides, preferably use null_ptr instead of NULL in your code. Since C++11, this is the standard for null pointers.
I add TEST_TRUE and then that work correctly.

Segmentation fault after allocating new memory

I am trying to return the root node of a BST. My recursive function involves using std::vector as a container for SPnodes (the tree node object) which during a single call is iterated over and a vector with fewer elements is passed up to the next call. Once the vector is of size 1, my function returns a new SPnode which is created by calling the copy constructor on the first (and only) element in nodeList, the vector container.
This is then passed through the wrapper function and then to the original caller.
Question
I understand that when the vector container goes out of scope it is destroyed, however I'm allocating new memory and copying the SPnodes so I don't understand how this could be causing the problem. So then, what is causing this? I doubt my problem is unique, but I can't seem to find an answer after going through countless SO questions.
Code
SPnode header:
#ifndef SPNODEOBJ_H
#define SPNODEOBJ_H
#include "IntervalObjects.h"
#include "IntervalObj.h"
#include "InVecObj.h"
#include "StandardLib.h"
// --- SPnode Class ------------------------------------------------------------
// SPnode (or Subpaving Node), is a node in a binary tree which contains a
// parameter "box" which is an InVec object, and a left and right child which
// are also SPnode objects. These SPnode objects are the resultant boxes from
// calling the expand method on m_box. This implementation allows for two
// important characteristics: there is a way to determine "where" a given box in
// a subpaving is by iterating over a node's left or right child, which in turn
// allows for greater efficiency; secondly, the tree structure gives a "history"
// of the subpaving, which allows for the determination of parent boxes.
class SPnode
{
private:
InVec m_box;
// left and right children of this SPnode object - note that these must be
// pointers in order to use them in the definition of the class, otherwise
// SPnode would reference itself in its definition
SPnode* m_left;
SPnode* m_right;
// a boolean sepcifying whether the SPnode m_box is in the given subpaving
bool m_inSP;
bool m_hasBeenIterated;
public:
SPnode(InVec box): m_box(box), m_left(NULL), m_right(NULL), m_inSP(true),
m_hasBeenIterated(false) {}
SPnode(const SPnode &ASP)
{
recConstructor(this, ASP);
}
void recConstructor(SPnode* const &parent, const SPnode &ASP);
void recDestructor(SPnode* const &ASP);
~SPnode() {delete m_left;
delete m_right;}
// getters and setters
InVec getBox() const {return m_box;}
SPnode* getLeft() const {return m_left;}
SPnode* getRight() const {return m_right;}
bool getInSP() const {return m_inSP;}
bool getIterated() const {return m_hasBeenIterated;}
void setBox(const InVec box) {m_box = box;}
void setLeft(SPnode* const p_node) {m_left = p_node;}
void setRight(SPnode* const p_node) {m_right = p_node;}
void setInSP(bool truth) {m_inSP = truth;} // when this is called truth
// should only be false
void setIterated(bool truth) {m_hasBeenIterated = truth;}
bool isLeaf() const;
friend std::ostream& operator<< (std::ostream &out, const SPnode &ASP);
SPnode operator=(const SPnode& ASP)
{
std::cout << "assignment called\n";
if (this == &ASP) return *this;
recConstructor(this, ASP);
return *this;
}
friend void expand(SPnode &ASP);
friend InVec lower(const InVec &box, const Interval &width, int axis);
friend InVec upper(const InVec &box, const Interval &width, int axis);
friend void mince(SPnode &ASP);
friend SPnode regularize(ImList &list, InVec box);
friend SPnode* recRegularize(std::vector<InVec> &list, SPnode &parentNode);
};
#endif
SPnode cpp file:
#include "SPnodeObj.h"
void SPnode::recConstructor(SPnode* const &parent, const SPnode &ASP)
{
parent->m_box = ASP.m_box;
parent->m_inSP = ASP.m_inSP;
parent->m_hasBeenIterated = ASP.m_hasBeenIterated;
if (ASP.isLeaf())
{
parent->m_left = NULL;
parent->m_right = NULL;
return;
}
if (ASP.m_left == NULL)
{
parent->m_left = NULL;
}
if (ASP.m_right == NULL)
{
parent->m_right = NULL;
}
if (ASP.m_left != NULL)
{
parent->m_left = new SPnode((ASP.m_left)->m_box);
}
if (ASP.m_right != NULL)
{
parent->m_right = new SPnode((ASP.m_right)->m_box);
}
if (ASP.m_left != NULL)
{
recConstructor(parent->m_left, *(ASP.m_left));
}
if (ASP.m_right != NULL)
{
recConstructor(parent->m_right, *(ASP.m_right));
}
}
bool SPnode::isLeaf() const
{
return (m_left == NULL && m_right == NULL);
}
std::ostream& operator<< (std::ostream &out, const SPnode &ASP)
{
if (ASP.m_right == NULL && ASP.m_left != NULL)
{
out << "SPnode(SPnode, " << ASP.m_box << ", NULL)";
}
else if (ASP.m_left == NULL && ASP.m_right != NULL)
{
out << "SPnode(NULL, " << ASP.m_box << ", SPnode)";
}
else if (ASP.m_left == NULL && ASP.m_right == NULL)
{
out << "SPnode(NULL, " << ASP.m_box << ", NULL)";
}
else
{
out << "SPnode(SPnode, " << ASP.m_box << ", SPnode)";
}
return out;
}
and my functions:
SPnode* listToTree (std::vector<InVec> boxList)
{
int counter = 0;
std::vector<SPnode> nodeList;
for (auto box : boxList)
{
nodeList.push_back(SPnode(box));
counter += 1;
}
//return recListToTree(nodeList);
//return new SPnode(*(recListToTree(nodeList)));
return recListToTree(nodeList);
}
SPnode* recListToTree (std::vector<SPnode> &nodeList)
{
std::cout << "nodelist size is: " << nodeList.size() << "\n";
if (nodeList.size() == 1)
{
return new SPnode(nodeList.at(0));
}
std::vector<SPnode> parentNodeList;
int counter = 0;
for (auto node : nodeList)
{
if (node.getIterated())
{
counter += 1;
continue;
}
if (counter + 1 == nodeList.size())
{
parentNodeList.push_back(SPnode(node.getBox()));
break;
}
if (node.getBox().isAdjacent(nodeList.at(counter + 1).getBox()))
{
SPnode newNode =
SPnode(node.getBox().combine(nodeList.at(counter + 1).getBox()));
if (lessThan(node.getBox(), nodeList.at(counter + 1).getBox()))
{
newNode.setLeft (new SPnode(node));
newNode.setRight(new SPnode((nodeList.at(counter + 1))));
}
else
{
newNode.setRight(new SPnode(node));
newNode.setLeft (new SPnode((nodeList.at(counter + 1))));
}
parentNodeList.push_back(SPnode(newNode));
nodeList.at(counter).setIterated(true);
nodeList.at(counter + 1).setIterated(true);
counter += 1;
}
else
{
parentNodeList.push_back(SPnode(node.getBox()));
nodeList.at(counter + 1).setIterated(true);
counter += 1;
}
}
recListToTree(parentNodeList);
}
Any help is appreciated!
recListToTree does not return a value on all paths, as there is not return at the end of the function (crank up the warning level in the compiler for it to tell you this). This garbage return value is the likely cause of your crashes.
Not related to the crash, but a memory leak problem, is that recConstructor is overly complicated (all those duplicated ifs) and will copy things twice (once via the copy constructor invoked by new, and once later by the recursive call to recConstructor).

C++ Iterator class

class ZoningIter
{
private:
CTile::Zonings mZoning;
CCity *mCity;
int mPos; ///< Position in the collection
public:
ZoningIter(CCity *tile, int pos, CTile::Zonings zoning) : mCity(tile), mPos(pos), mZoning(zoning)
{
while (mPos < mCity->mTiles.size())
{
if (mCity->mTiles[mPos]->GetZoning() == mZoning)
break;
else
mPos++;
}
}
bool operator!=(const ZoningIter &other) const
{
return mPos != other.mPos;
}
std::shared_ptr<CTile> operator *() const
{
return mCity->mTiles[mPos];
}
const ZoningIter& operator++()
{
auto size = mCity->mTiles.size();
auto myzone = mCity->mTiles[mPos]->GetZoning();
while (mPos < size-1)
{
++mPos;
if (mCity->mTiles[mPos]->GetZoning() == mZoning)
break;
}
return *this;
}
};
Not sure what am I doing wrong in this iterator. This class Iterator is suppose to loop over the class CCity and compare the tiles coming back with the ones that I am looking for.
one issue that I can see it run into an infinite loop not sure how to fix it ? any ideas?
You are running into an infinite loop because your operator++ won't increment to one past all elements, also known as an end-iterator.
while (mPos < size-1) // <-- This line is wrong, stops too early
It masks the error in the check-for-success you do afterwards.
Anyway, it should start with an increment, and then check whether it can and should loop.
A corrected version, with both bugs removed:
const ZoningIter& operator++() {
while( ++mPos < mCity->mTiles.size()
&& mCity->mTiles[mPos]->GetZoning() != mZoning)
{}
return *this;
}
Also, the return-type of operator*() should be const std::shared_ptr<CTile>&, the caller can make a copy if needed.

Single assignment for basic types in C++

I'd like to create a "single assignment" wrapper for basic types (such as int) that talks like an int, walks like an int, smells like an int, but can only be modified or assigned to at most once (like in some pure functional languages). For example (copy constructor omitted to keep the example simple):
template<class T>
struct SA {
SA<T>(T init) : wasAssigned(false) {
val = tmp = init;
}
SA<T> & operator=(const T& other) {
if (!wasAssigned) {
if (val != tmp) {
val = tmp;
} else {
val = tmp = other;
}
wasAssigned = true;
}
return *this;
}
operator T& () {
if (!wasAssigned && (val != tmp)) {
wasAssigned = true;
val = tmp;
} else {
tmp = val;
}
return tmp;
}
private:
bool wasAssigned;
T val, tmp;
};
This is close, but not perfect. It relies on the val/tmp equality test to detect changes, and fails in this case:
SA<int> i(3);
cin >> i;
i = 5;
Iff the cin >> i assigns the same value as the initial value (3), i will be 5 at the end. How can this be fixed?
Something like the following might work, although I'm not 100% sure about the side-effects. Basically returning a reference to tmp on all but the first call that gets a non-const reference, plus const methods for read-only access.
operator T& () {
if (wasAssigned) {
tmp = val;
return tmp;
} else {
wasAssigned = true;
return val;
}
}
operator const T& () const {
return val;
}
operator T () const {
return val;
}