Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
DoctorTristan
Mar 11, 2006

I would look up into your lifeless eyes and wave, like this. Can you and your associates arrange that for me, Mr. Morden?
Quick and stupid question: I'm writing a smart container that owns the pointers I push to it, and I want to ensure that the objects these point to are unchanged for their lifetime.

Can I do this as:

code:
class MyContainer {
  
  typedef std::vector<MyObject*> PStore;

  PStore storage;
  ...

public:
  MyContainer();
  ~MyContainer();
  ...
  push_back( const MyObject* obj ) {
    storage.push_back( obj )
  }

};

MyContainer::~MyContainer() {
  typename std::vector<MyObject*>::iterator i = storage.end();
  while( i != storage.begin() ) {
    delete i;
    i = 0;
  }
}

Is there any problem in insisting that push_back() takes a pointer to a const MyObject, and have I managed to avoid screwing up my iterators in the destructor definition?

Adbot
ADBOT LOVES YOU

DoctorTristan
Mar 11, 2006

I would look up into your lifeless eyes and wave, like this. Can you and your associates arrange that for me, Mr. Morden?

Mustach posted:

PStore should be a vector of const MyObject*s, push_back() needs a return type, that while-loop is infite if storage contains at least one element, and (related to the previous) I don't know what you're trying to do with i = 0, but it's not the right thing.

:doh:

I swear that some of those mistakes only crept in when I wrote up that post...

I wasn't quite sure abot the i=0 thing myself actually, I actually stole it from a generic purging template function from Eckel vol. 2, I assumed it was some kind of safety feature that I didn't quite get. What he wrote was:

code:
template<class Seq> void purge(Seq& c) {
  typename Seq::iterator i;
  for(i = c.begin(); i != c.end(); ++i) {
    delete *i;
    *i = 0;
  }
}

DoctorTristan
Mar 11, 2006

I would look up into your lifeless eyes and wave, like this. Can you and your associates arrange that for me, Mr. Morden?
Great, thanks guys. Some of those stupid errors were typos, but a lot were just me being plain dumb.

DoctorTristan
Mar 11, 2006

I would look up into your lifeless eyes and wave, like this. Can you and your associates arrange that for me, Mr. Morden?
I have another question about proper use of const. I want to define a compile-time constant that specifies how much space to reserve when initialising certain vectors; which I'll need to use in several places in my class definitions. Can I do this by creating a myconstants.h as follows:

code:
#ifndef MYCONSTANTS_H
#define MYCONSTANTS_H

  const int initialisationSize = 1000;

#endif
and adding #include "myconstants.h" in any file where I need it? Or do I need to do it using an extern? Lastly, does the constant need to be in the same namespace as the class implementation that needs to see it?

DoctorTristan
Mar 11, 2006

I would look up into your lifeless eyes and wave, like this. Can you and your associates arrange that for me, Mr. Morden?
What's the scope of a typedef? I'm wondering if it's legal to do something like:
code:
template<class T>
class MyClass {
  typedef std::vector<double> doublesVector;
  ...
public:
  MyClass();
  ~MyClass();
  void myMethod();

};

template<class T>
MyClass::myMethod() {
  doublesVector storage;
  ...
}
Will the implementation still see the typedef, or would I need to re-declare it?

(I know the template isn't doing anything here; I left it in to explain why I've got the class definition and implementation in the same file)

DoctorTristan
Mar 11, 2006

I would look up into your lifeless eyes and wave, like this. Can you and your associates arrange that for me, Mr. Morden?

TSDK posted:

Yup, that's perfectly fine, you don't need to typedef it again.

Thanks. Just so I'm clear, would this still work if I had separate files for the declaration and implementation? (I think it would).

DoctorTristan
Mar 11, 2006

I would look up into your lifeless eyes and wave, like this. Can you and your associates arrange that for me, Mr. Morden?
Okay, I have a class, LogisticParameter, that contains two doubles: r and sigma. I want sigma to be a constant that takes the same value across all instances of LogisticParameter. Unfortunately I can't make sigma a static const because I won't know the value I want until execution of main().

The least messy way I can think of getting round this is to wrap the constructor for Logistic Parameter in a function object and use a global instance of that wrapper to create LogisticParameter:

code:
class LogisticParameter {
double r, sigma;
public:
LogisticParameter(double rval, double sigmaval) : r(rval), sigma(sigmaval) {}
~LogisticParameter()
};

class LogisticConstructorWrapper {
double savedSigma;
public:
LogisticConstructorWrapper(double sigmaval): savedSigma(sigmaval) {}
*LogisticParameter operator()(double rval) {
  return new LogisticParameter(rval, savedSigma);
 }
};
Is there a better way of doing this?

DoctorTristan
Mar 11, 2006

I would look up into your lifeless eyes and wave, like this. Can you and your associates arrange that for me, Mr. Morden?

That Turkey Story posted:

Maybe I'm misunderstanding, but why can't you just make it a non-const static that gets initialized in main?

Because I misunderstood the rules for initialising static members. Crisis over.

DoctorTristan
Mar 11, 2006

I would look up into your lifeless eyes and wave, like this. Can you and your associates arrange that for me, Mr. Morden?
What happens when you pass a pointer argument to a function that takes a reference, and vice versa? i.e.
code:
void func1(MyClass* foo) {}
void func2(MyClass& foo) {}

int main() {

  MyClass bar;

  func1(bar&);
  func2(&bar);

  return 0;
}
Are either of these legal?

DoctorTristan
Mar 11, 2006

I would look up into your lifeless eyes and wave, like this. Can you and your associates arrange that for me, Mr. Morden?
I've never quite worked out what the scope of a typedef is. If I have a header file myheader.h :

code:
typedef Foo Foo_alias;

void myfunc();
...
then will Foo_alias be visible in any .cpp or .h file that #includes "myheader.h"?

DoctorTristan
Mar 11, 2006

I would look up into your lifeless eyes and wave, like this. Can you and your associates arrange that for me, Mr. Morden?
Okay, this has got me stumped. I have a class, EA2Skeleton, that contains a public member segmentStore, a standard vector of pointers to another class. The copy constructor has to do some weird stuff with the elements of segmentStore, I've tried to implement this as:

code:
EA2Skeleton::EA2Skeleton ( const EA2Skeleton& skel ) {
        //This is fine
        std::vector<EA2SkeletonSegment*>::iterator it = segmentStore.begin();

        //This gives me errors
        std::vector<EA2SkeletonSegment*>::iterator skelit = ((skel).segmentStore).begin();

        //does some stuff with the iterators after this

        }
However I get the compiler error:

code:
 ea2skeleton.cpp: In copy constructor 'ea2::EA2Skeleton::EA2Skeleton(const ea2::EA2Skeleton&)':
ea2skeleton.cpp:33: error: conversion from
'__gnu_cxx::__normal_iterator<ea2::EA2SkeletonSegment* const*, std::vector<ea2::EA2SkeletonSegment*, std::allocator<ea2::EA2SkeletonSegment*> > >' 
to non-scalar type 
'__gnu_cxx::__normal_iterator<ea2::EA2SkeletonSegment**, std::vector<ea2::EA2SkeletonSegment*, std::allocator<ea2::EA2SkeletonSegment*> > >'
I guess the problem is something to do with the type of the const reference, but I'm not sure how to fix it.

DoctorTristan
Mar 11, 2006

I would look up into your lifeless eyes and wave, like this. Can you and your associates arrange that for me, Mr. Morden?
I've got linker/compiler error that I'm too stupid to see here. Sorry for all the :words:

The commands
code:
g++ -g -Wall -c testbb.cpp
g++ -g -Wall -c ea2functions.cpp
g++ -g -Wall -c ea2skeletonsegment.cpp
g++ -g -Wall testbb.o ea2functions.o ea2skeletonsegment.o -lgsl -o testbb
gives me a bunch of identical errors like this one:

code:
ea2functions.o: In function `ea2::markedPoisson(ea2::PathObservation const&, ea2::PathObservation const&, 
    ea2::EA2SkeletonSegment&, ea2::CellPoissonRatesMessenger const&, bool*, gsl_rng const*)':
/home/stats/strgao/EA2PerfectSimulation/ea2functions.cpp:165: undefined reference to `ea2::EA2SkeletonSegment::empty()'
code:
collect2: ld returned 1 exit status
The line in ea2functions.cpp that causes the error (unnecessary stuff trimmed):
code:
void markedPoisson ( ... EA2SkeletonSegment& output, ... ) {
    assert ( output.empty() );
...
}
ea2::EA2SkeletonSegment::empty() is defined in that class's header file:
code:
#ifndef EA2EA2SKELETONSEGMENT_H
#define EA2EA2SKELETONSEGMENT_H

#include <deque>
#include "ea2constants.h"
#include "pathobservation.h"
#include "pathminandtime.h"

namespace ea2 {
class EA2SkeletonSegment{  
public:

    std::deque<double> poissonTimes;
    std::deque<double> poissonMarks;
    std::deque<double> diffPoints;
    PathObservation start;
    PathObservation end;
    PathMinAndTime min;
    
    EA2SkeletonSegment();
    EA2SkeletonSegment(const PathObservation& startval, const PathMinAndTime& minval, const PathObservation& endval);
    ~EA2SkeletonSegment();
    bool empty();
    
};
}
#endif
and defined in the implementation :
code:
#include "ea2skeletonsegment.h"
#include "ea2constants.h"

...

bool ea2::EA2SkeletonSegment::empty() {
    bool val = poissonTimes.empty() && poissonMarks.empty() && diffPoints.empty();
    return val;
}
As far as I can see everything that needs to be #included is, so I'm not sure why this isn't compiling. Going on previous mistakes this is likely something very basic that I've overlooked - anyone have any ideas?

DoctorTristan
Mar 11, 2006

I would look up into your lifeless eyes and wave, like this. Can you and your associates arrange that for me, Mr. Morden?

Painless posted:

This is a linker error - the linker can't find the implementation for empty(). Try moving the linker input files to the end of the gcc command. I don't think that's supposed to matter but whatever. If that doesn't work, objdump -t ea2skeletonsegment.o and see if it contains empty().

Turned out that the problem was that I'd declared empty() as inline in th implementation file. Could someone clarify this for me - is it an error to declare a method as an inline like this?

What I had (which caused linker errors) was

myclass.h:
code:
Class MyClass{
public:
/* Boilerplate*/

bool empty()
};
myclass.cpp:
code:
inline bool MyClass::empty() { /*implementation*/ }

DoctorTristan
Mar 11, 2006

I would look up into your lifeless eyes and wave, like this. Can you and your associates arrange that for me, Mr. Morden?
Dumb question - am I right in thinking that pow(double, int ) is defined in <math>? So I can call pow(x, 3) to cube a double x without having to pay the cost of a pow(double, double) call?

DoctorTristan
Mar 11, 2006

I would look up into your lifeless eyes and wave, like this. Can you and your associates arrange that for me, Mr. Morden?
Sorry, meant <cmath>. Yes, I'm working in C++.

DoctorTristan
Mar 11, 2006

I would look up into your lifeless eyes and wave, like this. Can you and your associates arrange that for me, Mr. Morden?
Thanks. Stupid question round 2 is about for() loop scoping. If I write
code:
f(int i=1; i!=10; ++i) {
  int p = 1
  
  //do stuff with p

}
then p is local to the loop, but will each iteration of the loop see a different p?

DoctorTristan
Mar 11, 2006

I would look up into your lifeless eyes and wave, like this. Can you and your associates arrange that for me, Mr. Morden?
Point taken. Thanks again.

DoctorTristan
Mar 11, 2006

I would look up into your lifeless eyes and wave, like this. Can you and your associates arrange that for me, Mr. Morden?
Am I right in thinking that if I have a class with a public static member, I should always initialise it in a .cpp file and not in the header?

In case anyone wants the background, I had a class defined in the following header (no .cpp file):

logisticcell.h
code:
#ifndef LOGISTICCELL_H
#define LOGISTICCELL_H

class LogisticCell {
public:
  static double b;

  ///everything else

};

double LogisticCell::b = 0;

#endif
When I tried to compile my project I got a load of compiler errors complaining about multiple initialisations of the static member b. I think that the problem was that I was creating several .o files depending on logisticcell.h: my target then saw a separate initialisation in each .o and complained.

My solution was to create logisticcell.cpp, move the initialisation into there, then compile logisticcell.o and edit the project dependencies accordingly.

As I said, I've already found a solution to this, but wanted to check that I've done the right thing.

DoctorTristan
Mar 11, 2006

I would look up into your lifeless eyes and wave, like this. Can you and your associates arrange that for me, Mr. Morden?
A Monte Carlo algorithm I'm implementing involves a bunch of objects of class Container, these all contain a sequence of pointers to objects of class Segment. Two objects of class Container are considered equal if they point to the same Segment objects. All Containers are of equal length. The attachment hopefully illustrates what I'm going on about.

At one point in my algorithm I have a whole bunch (tens of thousands at least) of these Containers and I have to eliminate all the duplicates. I was considering doing this by implementing an operator<(...) for the class and inserting all the containers into a an set to remove duplicates, but I'm slightly worried about ownership problems.

Currently the containers are all kept in a deque and are created in such a way that the first container in the deque that points to a segment owns that segment (ownership is implemented with a bool vector - I've tried to show all this on the diagram). I *think* that inserting them into a set won't cause problems so long as the copy constructor creates a copy without ownership: insertion creates a non-owning copy inside the set, and the Segments will be destroyed when I purge the original deque from the back (the MC algorithm is such that the set will never outlast the deque).

Will this approach work? Computational time is also something of an issue here, so if anyone knows an alternative method that is/might be faster, please put me right.

Only registered members can see post attachments!

DoctorTristan
Mar 11, 2006

I would look up into your lifeless eyes and wave, like this. Can you and your associates arrange that for me, Mr. Morden?

Avenging Dentist posted:

Why would you make copies of the Segments instead of just inserting pointers to them in the set?

Sorry, that wasn't clear. I'm not copying the Segments - I'm (thinking of) inserting the Containers into the set. I was unsure whether having a copy-constructor for Container that kept ownership with the original would prevent the ownership getting confused.

Maybe I should provide a bit more detail. At a particular point I have a whole bunch of pointers to Containers in a deque, these containers in turn point to a (bigger) bunch of Segments floating around on the heap. Multiple containers may point to the same Segment. The ownership is set up so that if I delete the Containers by from the back of the deque to the front then everything gets cleaned up properly.

What I'm trying to do is eliminate all duplicate Containers, apply a particular function exactly once to each Container, then clean up every Container and Segment and move onto the next iteration. I wanted to make sure that I've correctly understood how insertion into a set works - I thought it called the copy-constructor to create a copy of the object inside the set.

Edit: by `duplicate containers' I mean `two different containers that point to the same ordered sequence of Segments'.

Edit2: If you can follow all of this, you're doing a lot better than I did. This algorithm took two full papers to describe properly. The reason I'm being vague about some of the details is because the details loving hurt.

Avenging Dentist posted:

Also lol at vector<bool>.

...yeah. That bit was one of the first things I implemented, before I found out how hosed-up vector<bool> actually is. Changing it is on the to-do list. Coding this algorithm has been quite the learning curve.

DoctorTristan fucked around with this message at 20:09 on Jun 4, 2009

DoctorTristan
Mar 11, 2006

I would look up into your lifeless eyes and wave, like this. Can you and your associates arrange that for me, Mr. Morden?

Avenging Dentist posted:

Ok, so $AvengingDentist->last() =~ s/Segment/Container/;

I am a stupid noob - please explain?

Avenging Dentist posted:

(Quiz: How would you know which of the original Containers the ones in your set referred to if the set only contained copies of them?)

Wouldn't know, wouldn't care. As long as the copy points to the same Segments as the original, it's identical so far as the algorithm is concerned.

What the algorithm wants to do is apply a particular function exactly once to each unique Container in the original collection. i.e. if there are two Container objects pointing to the same Segments, I want to apply the function to only one of them (and since the algorithm considers them identical it doesn't matter which). Once it's done this it has no further use for any of the Segments or Containers, so I then have to clean all those up.

Creating an appropriate operator<(...) for Container and inserting the Containers into a set to create a set of copies without duplicates seemed like the most convenient way to achieve that. Since I have a history of shafting myself with C++, I wanted to check that I hadn't misunderstood how a set works, or overlooked an easier or faster way, or done something that would gently caress up the ownership and prevent proper cleanup.

DoctorTristan
Mar 11, 2006

I would look up into your lifeless eyes and wave, like this. Can you and your associates arrange that for me, Mr. Morden?

Avenging Dentist posted:

If you're deleting everything when you're done, what I said was irrelevant, but it's still a waste to make a copy of the container when you could store a pointer to it. Pointers are much easier to copy than large objects.

:doh: Of course. So instead of an overloaded operator<(...) in Container I just create a comparison class that takes two pointers to Container and the whole thing works with less overhead. Thanks.

DoctorTristan
Mar 11, 2006

I would look up into your lifeless eyes and wave, like this. Can you and your associates arrange that for me, Mr. Morden?
This is a bug I already fixed, but wanted to make sure I understood the problem correctly.

I was trying to create a bunch of MyObj objects on the heap, and push pointers to those objects into a vector<MyObj*> vec . I was (incorrectly) doing this by iterating:

code:
vec.push_back( new MyObj( args ) );
Which resulted in every element of vec pointing to the same memory location. Changing this to
code:

MyObj* pObj = new MyObj( args );
vec.push_back( pObj );
fixed the problem.

I *think* what was happening was that new was only creating temporary objects, so at the next iteration it went looking for another block of heap memory of the same size and found the same block as with the previous iteration. Is my guess right?


Edit: doing this didn't actually fix anything. See my post three posts down.

DoctorTristan fucked around with this message at 17:16 on Jun 22, 2009

DoctorTristan
Mar 11, 2006

I would look up into your lifeless eyes and wave, like this. Can you and your associates arrange that for me, Mr. Morden?
Okay, the change I posted above didn't actually fix the problem, just moved everything around a bit, so I'm back to where I started.

Mustach posted:

What was in the for?

No for, just a sequence of method calls that run a few test cases (sorry if this is an incorrect usage of `iterating'). The whole thing's actually wrapped up in several layers of classes and structs; I simplified a lot of this above since I assumed it wasn't important, but what's actually going on is the following:

Big templated container class I'm pushing stuff into, with irrelevant members snipped out. The console output I've included comes from the member function at the end of this block (sorry for the very long names):
code:
template< class TParam, class TPhiFunc >
    class EA2ParameterAndSkeletonArray {
        private:

            typedef ParamAndPointerToSkel< TParam > ParamPointerPair;
            typedef std::list< ParamPointerPair > ListOfParamPointerPairs;
            typedef std::vector< ListOfParamPointerPairs* > VectorOfPointersToListOfParamPointerPairs;
            ParamPointerPair principalParameter;
            VectorOfPointersToListOfParamPointerPairs parameterStore;
            typename SetOfPointersToPairs::iterator iterToPrincipal;
        public:
            EA2ParameterAndSkeletonArray ( const int maxNumberOfSegments );
            ~EA2ParameterAndSkeletonArray();
            void addParameter ( const TParam& param );
        };

template< class TParam, class TPhiFunc >
    void EA2ParameterAndSkeletonArray< TParam, TPhiFunc >::addParameter ( const TParam& param ) {

        //EA2Skeleton* newskel = new EA2Skeleton(numSkeletonSegments);
        
        ( * ( parameterStore.begin() ) )->push_back ( ParamPointerPair ( param,  new EA2Skeleton(numSkeletonSegments) ) );
        //debugging code
        //TODO: remove once bug is fixed
        std::cout << "adding pair to store. Parameter value: "<< (parameterStore.front())->back().parameter.K 
        << " Address of skeleton is " << (parameterStore.front())->back().pToSkel << std::endl;
        ++numParams;
        return;

        }
Templated container struct I'm pushing into the big class above (where it's typedeffed to ParamPointerPair):
code:
template <class TParam>
struct ParamAndPointerToSkel {
    TParam parameter;
    EA2Skeleton* pToSkel;
    ParamAndPointerToSkel() : pToSkel(0) {}
    ParamAndPointerToSkel ( TParam inpParam, int numSegments ) : 
     parameter ( inpParam ) {pToSkel = new EA2Skeleton ( numSegments );}
    ParamAndPointerToSkel ( TParam inpParam, EA2Skeleton* inpPskel) :
     parameter ( inpParam ) , pToSkel ( inpPskel ) {}
    ~ParamAndPointerToSkel() {delete pToSkel;}
    };
`parameter' struct that will form one of the template parameters. The member 'K' is the only one that really matters for this example.
code:
namespace logistic {
    class LogisticParam {
        public:
            double r;
            double K;

            static double beta;
	    LogisticParam() {}
            LogisticParam ( double rI, double KI ) : r ( rI ), K ( KI ) {}
	    LogisticParam(const LogisticParam& par) : r(par.r), K(par.K) {}
	    ~LogisticParam(){}
        };
    }
relevant part of test.cpp:
code:
int main(){

...

    EA2ParameterAndSkeletonArray< logistic::LogisticParam, logistic::Phi >* arrayPoint1 = 
    new EA2ParameterAndSkeletonArray< logistic::LogisticParam, logistic::Phi > ( 3 );

    //create a bunch of LogisticParams with varying values of K:
    typedef logistic::LogisticParam logParam;
    logParam param1 = logParam ( 0.3, 1 );
    logParam param2 = logParam ( 0.3, 2 );
    logParam param3 = logParam ( 0.3, 3 );
    logParam param5 = logParam ( 0.3, 5 );

    //push these LogisticParams
    arrayPoint1->addParameter ( param1 );
    arrayPoint1->addParameter ( param2 );
    arrayPoint1->addParameter ( param3 );
    arrayPoint1->addParameter ( param5 );

...

return 0;
}
console output (produced by the member function at the end of the first block of code):
code:
adding pair to store. Parameter value: 1 Address of skeleton is 0x61be90
adding pair to store. Parameter value: 2 Address of skeleton is 0x61be90
adding pair to store. Parameter value: 3 Address of skeleton is 0x61be90
adding pair to store. Parameter value: 5 Address of skeleton is 0x61be90
So it appears to be creating and adding the ParamAndPointerToSkel appropriately, but they point to the same block of memory each time.

edit: table breaking

DoctorTristan fucked around with this message at 17:47 on Jun 22, 2009

DoctorTristan
Mar 11, 2006

I would look up into your lifeless eyes and wave, like this. Can you and your associates arrange that for me, Mr. Morden?
Thanks for spotting that. I'm pretty sure my C++ book warned about that very thing, but the lesson didn't sink in I guess.

So I guess the simplest solution would be to have the container class clean up the heap memory on destruction, rather than ParamPointerPair? (once I'm done with the ParamPointerPair objects I'm done with the container)

Will write better typedefs next time, promise.

DoctorTristan
Mar 11, 2006

I would look up into your lifeless eyes and wave, like this. Can you and your associates arrange that for me, Mr. Morden?
I've seen code by a few people that passes built-in types as const references, e.g.
code:
void f(const int& arg1, const double& arg2);
Is there any reason not to do pass-by-value with built-ins? I know why pass-by-const-reference is a good idea for more complex types, but it seems redundant here.

DoctorTristan
Mar 11, 2006

I would look up into your lifeless eyes and wave, like this. Can you and your associates arrange that for me, Mr. Morden?

Adhemar and ehnus posted:

answers

Thanks guys. On similar lines, I've seen other code where class methods obtain members as (*this).membername or this->membername. Is this done to protect against potential naming conflicts? So that you always get the member membername and not something in a more local scope with the same name?

DoctorTristan
Mar 11, 2006

I would look up into your lifeless eyes and wave, like this. Can you and your associates arrange that for me, Mr. Morden?
I'm getting something slightly odd with my STL containers. The problem occurs in the following function call

code:
equalSkeletons(**It, principalSkel);
The function definition is:
code:
bool equalSkeletons(const EA2Skeleton& left, const EA2Skeleton& right){

        return = std::equal((left.segmentStore).begin(), (left.segmentStore).end(), (right.segmentStore).begin() );
    }
The arguments **It, principalSkel are both of type EA2Skeleton:
code:
class EA2Skeleton {
 
            unsigned int maxlength;
        public:
            std::vector<EA2SkeletonSegment*> segmentStore;            
            EA2Skeleton ( int length );
            EA2Skeleton ( const EA2Skeleton& skel );
            ~EA2Skeleton(); 
            void push_back ( EA2SkeletonSegment* segArg );
	    int num_segs();
	    int num_points();
        };
This is a container class for pointers to type EA2SkeletonSegment: a class I've defined elsewhere. Yes, I know I'm storing them as public members.

What the function call is supposed to do is compare two EA2Skeletons by comparing the EA2SkeletonSegments they point to - if two EA2Skeletons point to the the same objects then they're considered equal.

The debugger is telling me that I'm dereferencing a past-the-end iterator during the evaluation (not sure if that's the right word) of the second argument to the function. This didn't happen in my testing, and I'm not sure why it's happening or how to fix it. Any thoughts?

DoctorTristan
Mar 11, 2006

I would look up into your lifeless eyes and wave, like this. Can you and your associates arrange that for me, Mr. Morden?

Avenging Dentist posted:

Why would you not check the length first? Aside from avoiding potential crashes, it'd be faster in most cases.

If the surrounding code is working properly then they should both be the same length already, but I'll stick an assert in and see if that catches anything.

Edit: Caught it! Messed up a conditional statement earlier on, one of the arguments was of size zero. I need to be more assertive.

DoctorTristan fucked around with this message at 09:46 on Sep 15, 2009

DoctorTristan
Mar 11, 2006

I would look up into your lifeless eyes and wave, like this. Can you and your associates arrange that for me, Mr. Morden?
Is type size_t always an alias for an unsigned integral type? So depending on the implementation it could be either an unsigned int or an unsigned long?

DoctorTristan
Mar 11, 2006

I would look up into your lifeless eyes and wave, like this. Can you and your associates arrange that for me, Mr. Morden?
If you want to check where you're going wrong you could always compile the program and step through it with a debugger, or if you haven't used a debugger yet you could just paste some printf blocks in and recompile:

code:
#include <stdio.h>

int main(int argc, char *argv[]) {
int x;
int y;
int z;
int *px;
int *py;
int *pz;

x = 1;
y = 2;
z = 3;
px = &x;
py = &y;
pz = &z;

/*value check*/
printf("x = %d, *px = %d\n", x, *px);
printf("y = %d, *py = %d\n", y, *py);
printf("z = %d, *pz = %d\n", z, *pz);

*px = *pz;

/*value check*/
printf("x = %d, *px = %d\n", x, *px);
printf("y = %d, *py = %d\n", y, *py);
printf("z = %d, *pz = %d\n", z, *pz);

y = *pz + 10;

/*value check*/
printf("x = %d, *px = %d\n", x, *px);
printf("y = %d, *py = %d\n", y, *py);
printf("z = %d, *pz = %d\n", z, *pz);

*pz = *py + x;

/*value check*/
printf("x = %d, *px = %d\n", x, *px);
printf("y = %d, *py = %d\n", y, *py);
printf("z = %d, *pz = %d\n", z, *pz);

py = px;

printf("x = %d, *px = %d\n", x, *px);
printf("y = %d, *py = %d\n", y, *py);
printf("z = %d, *pz = %d\n", z, *pz);

return(0);
}
It's ugly and a bad habit that you should try to avoid when writing actual code, but it's something I did when I was first learning C (back when I didn't know what a debugger was).

DoctorTristan
Mar 11, 2006

I would look up into your lifeless eyes and wave, like this. Can you and your associates arrange that for me, Mr. Morden?

Avenging Dentist posted:

This is especially important in C++, where you can keep things as lvalues by way of reference types. For instance, you can pass an array, without decay, to a function in C++: http://codepad.org/Ho2FMF0M

Pardon my ignorance, but does the T (&t)[N] in the declaration
code:
template<typename T, size_t N>
size_t array_len(T (&t)[N])
{
    return N;
}
mean that array_len takes a reference to an array of T of length N? It's a bit of syntax I haven't come across before.

I'm also guessing that using a lowercase 't' is arbitrary, and T (&a)[N] would have worked just as well.

DoctorTristan
Mar 11, 2006

I would look up into your lifeless eyes and wave, like this. Can you and your associates arrange that for me, Mr. Morden?

dekrob posted:

== Still didnt help, sorry i forgot to post the piece of code on last post

code:
	  if  (DAYNUM==1 && COL<DAY1 || DAYNUM>QDAYS);
{	
printf ("         "); 
}	
else 
{ 	
printf ("%9d",DAYNUM);
DAYNUM=DAYNUM+1;
}

Remove the ';' at the end of the if line - that's not the proper syntax.

You probably also ought to rethink how you indent your code.

edit - efb

Adbot
ADBOT LOVES YOU

DoctorTristan
Mar 11, 2006

I would look up into your lifeless eyes and wave, like this. Can you and your associates arrange that for me, Mr. Morden?

JLea posted:

pretty :downs: question

I'm trying to increase the initial value of X, and then decrease it by the same amount over Y seconds

Is Y an integer type?

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply