in C# I had the following class:
public class PixelInfo
{
public DateTime CreatedTime;
public float x;
public float y;
}
with the following code I was able to save multiple pixels:
private readonly List<PixelInfo> _pixels = new List<PixelInfo>();
foreach...
{
_pixels.Add(new PixelInfo()
{
CreatedTime = DateTime.Now,
x = xx,
y = yy,
});
}
Now I want to do the same in C++ and I tried it the following way:
std::list<PixelInfo> _pixels = {};
_pixels.push_back(new PixelInfo()
{
...
});
but this gives me an error. How can I save a List of multiple pixels using the class properties?
First of all, a C# List is not the same as a C++ std::list. In C# a list is more like a C++ std::vector, and it's std::vector that should be the default container to use.
Secondly, in C++ you don't have to use new to create objects. In fact, new in C++ creates an object somewhere in memory and returns a pointer to it. The result of new PixelInfo() will have the type PixelInfo* which is quite different from PixelInfo.
And thirdly, you can't initialize members of classes or structures in C++ like you do in C#.
I recommend using the emplace_back function of std::vector to create and initialize the objects:
std::vector<PixelInfo> _pixels;
// ...
_pixels.emplace_back(some_date_and_time, x, y);
Related
I am trying to add a few different members to a list, but when the list is added to it contains copies of only the last member added:
private PotentialSolution tryFirstTrack(PotentialSolution ps, List<PotentialSolution> possibleTracks)
{
for (Track trytrack = Track.Empty + 1; trytrack < Track.MaxVal; trytrack++)
{
if (validMove(ps.nextSide, trytrack))
{
ps.SetCell(trytrack);
possibleTracks.Add(ps);
}
}
return tryNextTrack(ps, possibleTracks);
}
The PotentialSolution class looks like this:
public class PotentialSolution
{
public Track[,] board;
public Side nextSide;
public int h;
public int w;
static int cellsPerSide;
static bool testing;
static int minTracks;
.....
public void SetCell(Track t)
{
board[h, w] = t;
}
}
So we are trying to make several copies of the board which only differ by which 'track' is placed in the current cell.
If I have a breakpoint at possibleTracks.Add(ps) then I can see by inspecting ps that the required cell contents is changing each time, as required.
But when the code reaches the next line (or the return statement), the cell content is the same in each member of the list (it's the last one that was added).
What I am doing wrong here? I have tried using an ArrayList and also a basic array instead, but get the same result. It's acting as though the board member is decared as static, but it's not.
[edit]
In response to those who suggested making copies of ps, you are correct and I had tried this before - but only tried single-stepping after the change and didn't run the full program (this method is used hundreds of times). When running the full program, making copies of ps certainly makes a difference to the result (although it's still not correct). The problem now, and why I didn't stick with using the copies, is that an added test still shows the list to contain the same versions of ps, even though the debugger has shown 2 or 3 different tracks being deployed:
private PotentialSolution tryFirstTrack(PotentialSolution ps, List<PotentialSolution> possibleTracks)
{
for (Track trytrack = Track.Empty + 1; trytrack < Track.MaxVal; trytrack++)
{
if (validMove(ps.nextSide, trytrack))
{
PotentialSolution newps = new PotentialSolution(ps);
newps.SetCell(trytrack);
possibleTracks.Add(newps);
}
}
// temporary test, can be removed
if (possibleTracks.Count >= 2)
{
PotentialSolution ps1 = new PotentialSolution(possibleTracks.First());
PotentialSolution ps2 = new PotentialSolution(possibleTracks.Last());
if (ps1.GetCell() != ps2.GetCell())
{
// should always get here but never does
int foo = 1;
}
}
return tryNextTrack(ps, possibleTracks);
}
By the way, Track and nextSide are just enum integers, they will be 0-6, and the list will contain 0,1,2,or 3 members, never more.
You are adding references to the same object: ps in possibleTracks.Add(ps)
You could add a constructor to PotentialSolution duplicating the class:
public class PotentialSolution
{
public Track[,] board;
public Side nextSide;
public int h;
public int w;
static int cellsPerSide;
static bool testing;
static int minTracks;
//.....
public PotentialSolution()
{
}
public PotentialSolution(PotentialSolution ps)
{
board = ps.board;
nextSide = ps.nextSide;
h = ps.h;
w = ps.w;
}
//.....
Then use:
private PotentialSolution tryFirstTrack(PotentialSolution ps, List<PotentialSolution> possibleTracks)
{
for (Track trytrack = Track.Empty + 1; trytrack < Track.MaxVal; trytrack++)
{
if (validMove(ps.nextSide, trytrack))
{
ps.SetCell(trytrack);
possibleTracks.Add(new PotentialSolution(ps)); // duplicate object
}
}
return tryNextTrack(ps, possibleTracks);
}
This creates a new instance of the class each time it is added to the list.
Consider giving the PotentialSolution type value semantics by making it a struct and implementing a Clone method, or a constructor that takes another PotentialSolution as an argument. Also, to clone a 2D array of value types, call Object.Clone() and cast the result to T[,].
When making a copy of your PotentialSolution, you'll need to make sure your clone your board array, because, in your case, each PotentialSolution keeps its own representation of the state of the board.
I feel like the critical part you're missing is how to shallow clone a 2D array, which in general, is:
T[,] copy = (T[,])original.Clone();
WARNING: Clone creates a shallow copy of the array. For value-types this copies the values of each element, so for your int-like "Track" type it does what you want, but for other readers who may be using reference-types (like classes) it does not clone each object referred to by each element of the array. The elements of the new array are just object references, and will still refer to the same objects referred to by the elements of the original array. See the documentation.
Full example below that changes the middle cell of a 3x3 board from A to B.
using System;
using System.Linq;
public enum Track { A, B, C }
public enum Side { X, Y, Z }
public struct PotentialSolution
{
public Track[,] board;
public Side nextSide;
public int h;
public int w;
public void SetCell(Track t)
{
board[h, w] = t;
}
public PotentialSolution(Track[,] board, Side nextSide, int h, int w)
{
this.board = (Track[,])board.Clone();
this.nextSide = nextSide;
this.h = h;
this.w = w;
}
public PotentialSolution Clone()
{
return new PotentialSolution(board, nextSide, h, w);
}
// This `ToString` is provided for illustration only
public override string ToString()
{
var range0 = board.GetLength(0);
var range1 = board.GetLength(1);
var b = board;
return string.Join(",",
Enumerable.Range(0, range0)
.Select(x => Enumerable.Range(0, range1)
.Select(y => b[x, y]))
.Select(z => "[" + string.Join(",", z) + "]"));
}
}
class Program
{
static void Main(string[] args)
{
Track[,] someBoard = new Track[3, 3];
PotentialSolution ps1 = new PotentialSolution(someBoard, Side.X, 1, 1);
ps1.SetCell(Track.A);
PotentialSolution ps2 = ps1.Clone();
ps2.SetCell(Track.B);
Console.WriteLine(ps1);
Console.WriteLine(ps2);
}
}
I'm filling in the blanks liberally, so please excuse any assumptions I have made that differ from your actual situation, because I have done so only to make this example self-contained. My ToString implementation and its usage of System.Linq is not necessary; it's purely for the purposes of displaying the 2D array in my example.
You always call SetCell on the same ps object you received as a parameter then add the same instance to the possibleTracks list. The result is: possibleTrack contains ps n times and because it is the same instance you used in each cycle it will have the last change you applied via SetCell call.
Not sure what you wanted to achieve but it looks you need a modified copy of ps in each cycle for adding to possibleTrack list. Making PotentialSolution a struct instead of class could be enough? Structs are copied in such a way but may hit your performance if PotentialSolution is big.
The board member will still generate the same problem, because despite ps will be copied but the board inside it will contain same Track references. The trick can be applied to Track too, but the performance issues may raise more.
Just implement a Clone on PotentialSolution to have fully detached instances of it, then call ````SetCell``` on cloned instance and add that instance to the list.
I want to know if is possible in Visual Studio 2005 C++ to create an ArrayList of objects of a class.
I will have this class:
class var
{
int x;
int y;
}
In C# is something like this: ArrayList<var> list = new ArrayList<var>(); , but in C++ doesn't work.
I forgot to mention that the project is a Windows Form Application.
Have you tried std::vector<var> myVector or std::list<var> myList?
That should do the job:
#include <vector>
using std::vector;
class var
{
int x;
int y;
};
int main(void)
{
vector<var> myVec(10); // creates a vector of 10 elements of var objects
// ... other stuff
return 0;
}
But there are many more ways to put objects into a vector, e.g. create an empty vector and using vector::push_back(), etc. You should read the Standard libs' documentation for all the alternatives.
You can do this:
var myArray[50];
Which are 50 vars on the stack. You can also do this:
var* myArray = new var[50];
Which are 50 vars on the heap. Or you could just use a std::vector:
var myObject;
std::vector <var> myVector;
myVector.push_back(var);
Or, the last one that I usually use is:
std::vector <var*> myVector;
var* pVar = new var();
myVector.push_back(pVar);
There are way too many ways of doing it, these are just a few.
I am developing a software that takes realtime-data and extracts a number of features from that depending on user input. Each available feature consists of one method that takes an array of doubles and return the wanted feature, such as this one for the MeanAbsoluteValue:
public static class MeanAbsoluteValue{
public static double Calculate(double[] data){
return data.Sum(s => Math.Abs(s)) / data.Length;
}
}
Since each of the features only has the one Calculate method I was thinking of trying to rewrite them so that they can be collected and chosen from that Collection.
I have tried writing an Interface for them to use, but since they are static this was not allowed.
Is there a way of doing this? And if so, could you point me in the right direction?
You can create an array of delegates constructed from the Calculate methods of these classes, like this:
Func<double[],double>[] array = new Func<double[],double>[] {
MeanAbsoluteValue.Calculate
, MeanValue.Calculate
, Deviation.Calculate
// ...and so on
};
Here is a demo on ideone.
Store delegates to your functions in a dictionary, and look them up by name
var methods = new Dictionary<string, Func<double[], double>>();
methods.Add("MeanAbsoluteValue", MeanAbsoluteValue.Calculate);
...
public double DoFunc(string name, double [] args)
{
var func = methods[name];
return func(args);
}
Just have a collection of Func...
var list = new List<Func<double[], double>(MeanAbsoluteValue.Calculate, Average.Calculate)
var accum = 0;
foreach(var func in list)
{
accum += func(new [] {1,3,4,});
}
I am using Mono Develop For Android and would like some help with using an array of structs.
Here is my code:
public struct overlayItem
{
string stringTestString;
float floatLongitude;
float floatLatitude;
}
And when using this struct:
overlayItem[1] items;
items[0].stringTestString = "test";
items[0].floatLongitude = 174.813213f;
items[0].floatLatitude = -41.228162f;
items[1].stringTestString = "test1";
items[1].floatLongitude = 170.813213f;
items[1].floatLatitude = -45.228162f;
I am getting the following error at the line:
overlayItem[1] items;
Unexpected symbol 'items'
Can I please have some help to correctly create an array of the above struct and then populate it with data.
Thanks
Define your struct like:
overlayItem[] items = new overlayItem[2];
Also you need to define your fields in the struct as public, to be able to access them outside the struct
public struct overlayItem
{
public string stringTestString;
public float floatLongitude;
public float floatLatitude;
}
(you may use Pascal case for your structure name)
You need to create your struct array like so:
overlayItem[] items = new overlayItem[2];
Remember to declare it with [2] as it will have 2 elements, not 1! Indexing an array might start at zero, but defining an array size does not.
Your sample code shows you need two items, so you need to declare the array of structs with length 2. This can be done with:
overlayItem[] items = new overlayItem[2];
The right way to declare the struct array for two elements is
overlayItem[] items = new overlayItem[2];
If you do not know the exact no of items you can also use list.
List<overlayItem> items = new List<overlayItem>();
items.Add( new overlayItem {
stringTestString = "test";
floatLongitude = 174.813213f;
floatLatitude = -41.228162f;
}
);
I am using NetTopologySuite for some simplificaiton of lines.
The issue I am facing is I have my own class that store list of Point3D (System.Windows.Media)
and NetTopology has its own Coordinate class with almost the same properties and functions.
To convert the point3D list to coorinate array I am using this function:
public static GeoApiInterfaces.ICoordinate[] ToCoordinateArray(this IEnumerable<Point3D> listToClone,
bool isClosed = false)
{
// if geometry is to be closed the size of array will be one more than the
// current point count
var coordinateList = new GeoApiInterfaces.ICoordinate[isClosed ?
listToClone.Count() + 1
: listToClone.Count()];
// loop through all the point in the list to create the array
int elementIndex = 0;
foreach (var point in listToClone)
{
var coordinate = new GeoApiGeometries.Coordinate(point.X,
point.Y,
point.Z);
coordinateList[elementIndex] = coordinate;
elementIndex++;
} // foreach
// if geometry is closed the add the first point to the last
if (isClosed)
{
var coordinate = new GeoApiGeometries.Coordinate(listToClone.ElementAt(0).X,
listToClone.ElementAt(0).Y,
listToClone.ElementAt(0).Z);
coordinateList[elementIndex] = coordinate;
} // if isClosed
return coordinateList;
}
Everything works fine, but when I profiled my code almost 95% time is taken by this function. I am wondering, are there any other ways to convert the list of System.Windows.Media.Point3D to Coordinate[].
Same will be true from one class to another conversion.
Update
If the collection is a List<> then we can do a one time reflection to the underlying array like this
static FieldInfo f_items = typeof(List<Point3D>).GetField("_items", BindingFlags.NonPublic | BindingFlags.Instance);
static FieldInfo f_size = typeof(List<Point3D>).GetField("_size", BindingFlags.NonPublic | BindingFlags.Instance);
and then use it code each time we want to convert as List<Point3D> into Point3D like this
Point3D[] array = f_items.GetValue(list) as Point3D[];
int size= (int)f_size.GetValue(list);
Then you can proceed with the code below. If the IEnumerable<> collections is something different then you need to find how the elements are stored internally first.
Original
I think if you can limit yourself to arrays instead of IEnumerable<> then you can achieve faster speeds.
Here an example code that is compact and shall work as fast as possible.
public struct Point3D
{
public double x, y, z;
}
public static class Extensions
{
public static ICoordinate[] ToCoord(this Point3D[] points, int size)
{
size = Math.Min(points.Length,size); //make sure there are enough points
ICoordinate[] res = new ICoordinate[size];
for (int i = 0; i < size; i++)
{
res[i] = new Coordinate(points[i].x, points[i].y, points[i].z);
}
return res;
}
}
class Program
{
static void Main(string[] args)
{
Point3D[] array1 = new Point3D[N];
// Fill the array ..
ICoordinate[] array2 = array1.ToCoord();
}
}
There's no way to make this method faster. You could buffer listToClone.ElementAt(0) in the last block, but that's hardly relevant to overall performance with long lists.
If the source & target coordinates were equivalent value types you could try tricks with pointers to copy their data directly. But sadly GeoApiGeometries.Coordinate is a reference type, presumably because the library was ported from Java, so you definitely must allocate each new element manually, just as you do now.
I was calling this function in foreach it replace that foreach to for and it improved the performance. I should have posted the whole code.