tags:

views:

280

answers:

4

Edit: My debugger was lying to me. This is all irrelevant

Howdy all,

I had a peek at http://stackoverflow.com/questions/637438/adding-element-to-vector, but it's not helpful for my case.

I'm trying to add an element (custom class LatLng) to another object (Cluster) from a third object (ClusterManager).

When I pass my LatLng to Cluster (last line of ClusterManager.cpp), and jump into Cluster::addLocation, at the end of the function execution gdb says my new LatLng has been added to Cluster, but the moment I jump back into the scope of the highest class, ClusterManager, the new LatLng added to the vector 'locStore' is not present in either runtime or debug.

Any ideas?

DJS.

DE: Xcode 3.2 (Targeted to Debug 10.5) OS: OSX 10.6 Compiler: GCC 4.2 Arch: x86_64

ClusterManager.cpp (where it's all being called from):

void ClusterManager::assignPointsToNearestCluster()
{
    //Iterate through the points.
    for (int i = 0; i < locationStore.size(); i++)
    {
     double closestClusterDistance = 100.1;
     // Make sure to chuck the shits if we don't find a cluster.
     int closestCluster = -1;
     int numClusters = clusterStore.size();
     // Iterate through the clusters.
     for (int j = 0; j < numClusters; j++) {
      double thisDistance = locationStore[i].getDistanceToPoint( *(clusterStore[j].getCentroid()) );

      // If there's a closer cluster, make note of it.
      if (thisDistance < closestClusterDistance) {
       closestClusterDistance = thisDistance;
       closestCluster = j;
      }
     }
     // Remember the penultiment closest cluster.
     this->clusterStore[closestCluster].addLocation( this->locationStore[i] );
    }
}

ClusterManager.h

#include "Cluster.h"
#include "LatLng.h"
#include <vector>

class ClusterManager{
private:
    std::vector<Cluster> clusterStore;
    std::vector<LatLng> locationStore;
public:
    ClusterManager();
    void assignPointsToNearestCluster();
    void addLocation(int,double,double);
};

Cluster.h:

#include <vector>
#include <string>

#include "LatLng.h"

class Cluster {
private:
    std::vector<LatLng> locStore;
    LatLng newCentroid;
    bool lockCentroid;
    int clusterSize;
    int clusterID;
public:
    Cluster(int,LatLng&);
    void addLocation(LatLng&);
    LatLng* getCentroid();
};

Cluster.cpp

Cluster::Cluster(int newId, LatLng &startPoint)
{
    this->clusterID = newId;
    this->newCentroid = startPoint;
};

void Cluster::addLocation(LatLng &newLocation)
{
    (this->locStore).push_back( newLocation ); 
};

LatLng* Cluster::getCentroid()
{
    return &newCentroid;
};
A: 

std::vector::push_back() expects a const reference as input, but you are passing it a non-const reference instead, so the compiler has to create a temporary LatLng object, which is what gets added to the vector instead of your original LatLng object.

Remy Lebeau - TeamB
A reference is automatically converted into a const reference. A copy of the `LatLng` object is inserted into the vector, but no temporary is created.
Tim Sylvester
This is not correct. The compiler simply silently casts the mutable reference into a const reference and uses that.
Peter
A: 

What does your copy constructor for the class LatLng look like? When you call std::vector::push_back(), a copy of the argument is made before adding it to the vector. The lack of a non-compiler-generated copy constructor may indicate why you are not seeing certain values in the target vector.

Also, you mention that you are getting an out-of-bounds error when iterating the contents of the vector. This suggests that there are fewer elements in the vector than you expected there to be. Consider iterating through the vector using a for-loop, bound by vector.size().

Steve Guidi
A: 

What does the copy constructor of LatLng do? This determines what actually winds up in the vector when you call push_back.

btw it's a bit more efficient to use iterators rather than indices in your vector loops - less operator[] usage, in favour of direct refs to vector members via the iterator.

Steve Townsend
+2  A: 

The debugger is possibly lying. I've found Xcode has issues has viewing the contents of vectors, try using some asserts to make sure the vector in question is actually being filled.

Justicle