push_back vector of pointers of pointers - c++

std::vector<BPatch_point *> *points;
points = functions[0]->findPoint(BPatch_entry);
if ((*points).size() == 0)
{
cout << "Failed to get the points" << endl;
}
std::vector<ldframework::Point *> *new_points;
for(unsigned int i = 0; i < points->size(); i++ )
{
ldframework::Point *pt1 = new ldframework::PointImpl((*points[0]));
new_points->push_back(pt1);
}
The PointImpl constructor is :
ldframework::PointImpl::PointImpl(const BPatch_point&* po)
{
Bpatch_point *_bpoint=new BPatch_point(*po);
}
WHile compiling im getting following error. Could you please help
>BfunctionImpl.cpp: In member function âvirtual const std::vector<ldframework::Point*, std::allocator<ldframework::Point*> >* ldframework::BfunctionImpl::find_Point(ldframework::locClass)â:
BfunctionImpl.cpp:86: error: expected type-specifier
BfunctionImpl.cpp:86: error: cannot convert âint*â to âldframework::Point*â in initialization
BfunctionImpl.cpp:86: error: expected â,â or â;â
THe 86 line number code is
ldframework::Point *pt1 = new ldframework::PointImpl((*points[0]));

Have a look at the (*points[0]) part of line 86.
Since points is a pointer to a vector and the array subscript operator [] has a higher precedence than the unary indirection operator *, this is parsed as *(*(points+0)).
You might try to replace this by (*points)[0] or maybe even: (*points)[i]
Furthermore, new_points is a pointer to a vector, that has not been assigned to a pointer to a valid object before it is used.
Additionally, I see that you use a lot of pointers, which causes extra indirections, decrease of locality, and gives you the burden of cleaning-up things or causing memory leaks. Does new_points have to be a vector of pointers to ldframework::Point? You could use a vector of std::unique_ptr<ldframework::Point> to avoid the clean-up burden, but you can also consider:
std::vector<ldframework::PointImpl> *new_points =
new std::vector<ldframework::PointImpl>;
for(unsigned int i = 0; i < points->size(); i++ )
{
new_points->push_back( ldframework::PointImpl((*points)[i]) );
}
or even better:
std::vector<ldframework::PointImpl> new_points;
for(unsigned int i = 0; i < points->size(); i++ )
{
new_points.push_back( ldframework::PointImpl((*points)[i]) );
}

Related

Change object of a QVector in an ordinary for loop

If I have a QVector I can use a range based loop, use a reference and change the objects in the QVector.
But in the case where I need the index while modifying the object I have to use an ordinary for loop. But how can I then change the value of the object in the QVector?
As workaround I used the replace method after changing the temporary object but that is kind of ugly.
This is the code:
struct Resource {
int value = 0;
};
int main(int argc, char *argv[])
{
QVector<Resource> vector{Resource{}, Resource{}, Resource{}};
qDebug() << vector.at(0).value
<< vector.at(1).value
<< vector.at(2).value;
for(Resource &res : vector)
res.value = 1;
qDebug() << vector.at(0).value
<< vector.at(1).value
<< vector.at(2).value;
for(int i = 0; i < vector.size(); ++i) {
//Resource &res = vector.at(i); <-- won't compile: cannot convert from 'const Resource' to 'Resource &'
Resource &res = vector.value(i); //Compiles, but creates temporary Object and doesn't change the original object
res.value = i;
//vector.replace(res); <-- Workaround
}
qDebug() << vector.at(0).value
<< vector.at(1).value
<< vector.at(2).value;
}
Use the array subscript operator, [].
Resource &res = vector[i];
or you can discard the reference variable and do a direct access:
vector[i].value = i;
This operator returns a non-const reference to the object at the specified index.
You can use T & QVector::operator[](int i), because it returns the item at index position i as a modifiable reference. But you are using const T & QVector::at(int i) const now (i.e. in both cases you have a reference, but in case of operator[] it is not constant).
So, you can do something like this:
for(int i = 0; i < vector.size(); ++i)
vector[i].value = i;

Class accept and return array

I try to create a class that accept and return an array but I got some problem. I'm not sure if it is legal to return an array from a class. Or it could be done by returning an pointer to the array. Thank for any solution to the problem.
#include <iostream>
using namespace std;
class myclass {
private:
int Array[10];
public:
myclass (int temp[10]) {
for (int i = 0; i < 10; i++) {
Array [i] = temp [i];
}
}
int returnArray () {
return Array; // error here, I'm not sure if it is legal to return an array.
}
int* returnArray2 () {
return this->Array; // hope it will return a pointer to the array
}
};
int main () {
int Array[10] = {1,2,3,4,5,6,7,8,9};
myclass A(Array);
cout << A.returnArray() << endl; // try to return an array and print it.
myclass* ptr = &A;
cout << *ptr->returnArray2 << endl; // error here
return 0;
}
First of all it is better to write the constructor either like
myclass ( const int ( &temp )[10] ) {
for (size_t i = 0; i < 10; i++) {
Array [i] = temp [i];
}
}
or like
myclass ( int temp[], size_t n ) : Array {} {
if ( n > 10 ) n = 10;
for (size_t i = 0; i < n; i++) {
Array [i] = temp [i];
}
}
Or even you may define the both constructors.
As for the returning value then you may not return an array. You may return either a reference to an array or a pointer to the entire array or a pointer to its first element
For example
int ( &returnArray () )[10] {
return Array;
}
In this case you can write in main
for ( int x : A.returnArray() ) std::cout << x << ' ';
std::cout << std::endl;
As for this statement
cout << *ptr->returnArray2 << endl; // error here
then you forgot to place parentheses after returnArray2. Write
cout << *ptr->returnArray2() << endl;
And the following member function is wrong because the expression in the return statement has type int * while the return type of the function is int
int returnArray () {
return Array; // error here, I'm not sure if it is legal to return an array.
}
So either the function will coincide with the the second member function if you specify its return type like int *. Or you could change the return expression to *Array
int returnArray () {
return Array; // error here, I'm not sure if it is legal to return an array.
}
This is illegal because Array is not of int type. Your returnArray2 is valid, however. As for this line:
cout << *ptr->returnArray2 << endl; // error here
This is illegal because returnArray2 is a function; you must call it to return the int*:
cout << *ptr->returnArray2() << endl; // prints the first value in the array
Other notes:
Your capitalization is backwards; you should call your class MyClass and your member array arr or arr_, or you will confuse a lot of people.
return this->Array; this is redundant, you can simply return Array;
If you haven't heard of std::vector and std::array you should research those, as they are generally superior to C-style arrays.
In general, I would suggest to read a c++ book to get your basics correct as there are lot of issues in the code you posted.
Regarding your main question about exposing C style arrays in class public API, this is not a very robust mechanism. Do it if it is absolutely essential because of existing code but if possible prefer to use std::vector. You will mostly always end up with better code.
Other answers have corrected your coding errors, so i won't repeat that.
One other thing, your code suggests that the array size is fixed. You can pass and return the array by reference as well. Refer to: General rules of passing/returning reference of array (not pointer) to/from a function?

Initializing chained hash table to NULL. Get "lvalue required as left operand of assignment" error. Why? Here is my code:

I am trying to create a chained hash table. I have started by building a dynamic array and am now trying to initialize each array pointer to NULL. But I get the error "lvalue required as left operand of assignment". Why? Here is my code:
#include <iostream> // for i/o functions
using namespace std;
const int HTSIZE = 997; //size of the hash table
struct CHTNode
{
int value;
CHTNode *next;
};
void InitializeTable(CHTNode* &cHT);
int main()
{
CHTNode *chainedHT;
chainedHT = new(nothrow) CHTNode[HTSIZE];
if (chainedHT == NULL)
{
cout << "ERROR: Memory allocation error"
<< endl;
return 1;
} //end if
else
{
InitializeTable(chainedHT);
}
}
void InitializeTable(CHTNode* &cHT)
{
for (int i = 0; i < HTSIZE; i++)
&cHT[i] = NULL; //ERROR FOR THIS LINE
}
The address-of operator & returns the address of the given expression, so &cHT[i] evaluates to the address of the ith element of cHT. It seems you're trying to assign to the variable cHT[i], but what you're doing right now is trying to assign to the address value of cHT[i], which makes no more sense than trying to assign to a constant.
You do not have an array of pointers. You allocated an array of objects of type CHTNode.
You could value initialize this array when it was allocated. For example
chainedHT = new(nothrow) CHTNode[HTSIZE] {};
If you want to write a separate function that zero-injitialize each element of the array then the function could be declared like
void InitializeTable( CHTNode* cHT, int n );
and defined like
void InitializeTable( CHTNode* cHT, int n )
{
for ( int i = 0; i < n; i++ ) cHT[i] = {};
}
As for erroneous statement
&cHT[i] = NULL;
then it does not make a sense. Expression &cHT[i] is a temporary object that you are try to assign.

make_pair(string, class): error: expected primary-expression before â)â token

error: expected primary-expression before â)â token
I'm not entirely sure what's going on here, since my friends also working on this project can't seem to tell what's wrong. Any help on this error would be appreciated. The line that the error is referring to has a comment on it pointing it out. I'm trying to insert a pair into a map by the code below.
theCandidates is a map<string, class>, and in this case, that class is called Candidate.
void TallyVotes::initialize(Scanner& inStream)
{
numberOfLosers = 0;
numberOfVotes = boost::lexical_cast<int>(inStream.next());
numberOfCandidates = boost::lexical_cast<int>(inStream.next());
for(int i = 0; i < numberOfVotes ; i++)
{
for(int j = 0; j < numberOfCandidates ; i++)
{
theVotes[i][j] = inStream.next();
cand = theVotes[i][j];
if(i == 0)
{
theCandidates.insert(make_pair(cand, Candidate));//ERROR ON THIS LINE
}
}
}
} // void TallyVotes::initialize(Scanner& inStream)
The make_pair function takes two values as arguments, not a value and a type.
Try e.g.
make_pair(cand, Candidate())
// Note parentheses ^^
The expression Candidate() create a temporary object, which is then copied into the std::map.

Set pointer to element in vector to null, then check whether pointer is null (C++)

I would like to set pointers to some elements in my vector array to NULL (based on a criteria), and then check whether an element pointer is NULL. If the pointer pointing that element is NULL, I remove the element from my vector array.
My compiler is giving me an error, saying that the address expression must be an lvalue or function designator and I do not understand why (line location commented in code). Since I am taking the address of the value using &, am I not seeing if the pointer pointing to that element is NULL?
I included the preceding code as the error may lie there,
Relevant code:
vector<particle> pl = c.particlelist;
vector<particle> noncollision = c.particlelist;
vector<vector<particle>> collisionlist = new vector<vector<particle>>();
for (int i = 0; i < c.numparticles-1; i++){
particle first = pl[i];
for (int j = i+1; j < c.numparticles; j++)
{
particle second = pl[j];
double d = distance(first, second);
if (d==0)
{
vector<particle> temp = {pl[i], pl[j]};
collisionlist.push_back(temp);
noncollision[i].setxposint(NULL);
noncollision[j].setxposint(NULL);
}
else
{
}
}
}
int j = 0;
for (int i = 0; i < noncollision.size(); i++)
{
if (&(noncollision[i].getxpos()) == NULL) ////// ERROR HERE
{
noncollision.erase(noncollision.begin()+i);
}
else
{
j++;
}
}
I am new to C++, and if you could suggest a more elegant way to do this, or a fix, it would be much appreciated. I also assume that my method of setting the pointer to an element, noncollision[i].setxposint(NULL); is correct? Can I return an integer using a function, and take the address?
Functions for getxpos and setxposint:
int particle::getxpos(){
return xpos;
}
void particle::setxposint(int b){
xpos = b;
}
You're using & to take a pointer to a temporary vale (the return from getxpos) which isn't allowed; since a temporary will be going away, the address won't be useful in any way so the language doesn't allow it. It certainly wouldn't ever be NULL even if you could get its address.
noncollision[i].setxposint(NULL);
All that line is doing is setting xpos to zero. Generally the term NULL is used with pointers, and 0 is used with things like integers. NULL is usually a macro for 0L anyway.
&(noncollision[i].getxpos()) == NULL
What this is doing, which is incorrect, is attempting to take the address of the return value from the member method getxpos() and compare it to NULL. Whereas what you really want to do is simply see if the function returns zero. So simply change this line to:
noncollision[i].getxpos() == 0
I'll explain why the compiler doesn't understand what you mean.
When you write
&(someFunction())
you are asking for the address of the thing that the function returns. But functions return values. A value doesn't have an address. Variables have addresses.
When something is a word of memory (which will contain a value), it can be used as an lvalue (left-value), because you can put things into that word of memory:
int b = 1; //make room for an `int` on the stack, then put a `1` there.
When something is just a value, it can only ever be used as an rvalue. The following would not compile, for the same reason that your code would not:
int b; //make room for an `int` on the stack.
42 = b; //ERROR, this makes no sense.
if (42 == NULL) { std::cout << "this is never true" << std::endl; }
&42; //ERROR, 42 isn't a piece of memory, it's a value.
(Caveat: you can use values to refer to words in memory: this usage is called a pointer, e.g.
int b = 1;
*((int *)(42)) = b;
meaning "put the value of b into the memory which has the address 42. This compiles fine (but crashes if you're not allowed to write to the memory at 42.)
It looks to me you're trying to keep track of 'visited' items, not sure exactly in which way.
Instead of "modifying" the items, you could use an "external" mark. A set looks to be fine here. You could use a set of iterators into the particle list, or in this case a set of indices (i,j) which will likely be more stable.
Here's a start:
#include <vector>
#include <set>
struct particle { };
double distance(particle const&, particle const&) { return 1.0; }
struct context
{
std::size_t numparticles;
std::vector<particle> particlelist;
context() : numparticles(100), particlelist(numparticles) {}
};
static context c;
int main()
{
using std::vector;
using std::size_t;
vector<particle> pl = c.particlelist;
vector<vector<particle>> collisionlist;
std::set<size_t> collision;
for(size_t i = 0; i < c.numparticles-1; i++)
{
particle first = pl[i];
for(size_t j = i+1; j < c.numparticles; j++)
{
particle second = pl[j];
double d = distance(first, second);
if(d < 0.0001)
{
collisionlist.push_back({pl[i], pl[j]});
collision.insert(i);
collision.insert(j);
}
else
{
}
}
}
for(size_t i = 0; i < pl.size(); i++)
{
if(collision.end() != collision.find(i))
{
// do something
}
}
// alternatively
for (int index : collision)
{
particle& p = pl[index];
// do something
}
}
NOTE Be very very wary of floating point comparison like
if (d==0.0) // uhoh
because it will likely not do what you expect
How dangerous is it to compare floating point values?
What is the most effective way for float and double comparison?
Is floating-point == ever OK?
It seems that you are trying to check pairs of points for collisions. You then record for each point whether it has any collision. This is best handled by a simple list of flags:
std::vector<bool> has_collision(c.numparticles, false); // init: no collisions found
Afterwards:
if (d==0)
{
has_collision[i] = true;
has_collision[j] = true;
}
At the end, iterate over the list of flags and get the points that have no collisions:
for (size_t i = 0; i < c.numparticles; ++i)
{
if (!has_collision[i])
{
// whatever
// possibly push_back pl[i] into some list
}
}
In addition: using a vector to hold a pair (i,j) of points is confusing. Standard library has the std::pair type for purposes such as this.
Also: you don't need explicit dynamic allocation (new); let Standard Library manage memory for you in a safe, non-confusing way. Instead of
vector<vector<particle>> collisionlist = *new vector<vector<particle>>();
Use
vector<vector<particle>> collisionlist;
(or vector<pair<particle, particle>>, as described above).