Brett
Brett

Reputation: 41

passing a double pointer by reference

I'm getting an error saying my expression must have a pointer to type class, I'm trying to dynamically allocate an array of pointers to an object vector.

void dmaArr(Record*** sortedRec, vector<Record> records) {
    //sortedRec = nullptr;
    *sortedRec = new Record *[records.size()];
    cout << *sortedRec << endl << sortedRec << endl;
    for (int i = 0; i < records.size(); i++) {
        *sortedRec[i] = &records[i];
        cout << sortedRec[i]->name << '\t' << &sortedRec[i]->name << endl;
    }

Upvotes: 0

Views: 77

Answers (2)

Remy Lebeau
Remy Lebeau

Reputation: 596156

sortedRec is a Record***, so sortedRec[i] is a Record**. You can't use the -> operator to dereference a pointer-to-pointer. You need to use the * operator instead to dereference the Record** pointer-to-pointer into a single Record* pointer, like you do in your for loop. Then, you can use the -> operator to dereference that Record* pointer to access the members of the Record instance, eg:

cout << (*sortedRec[i])->name << endl;

That being said, VERY VERY RARELY in C++ do you ever need to use 3 levels of indirection, like you are (Record*** sortedRec).

No matter how sortedRec is passed, records should be passed by reference so that dmaArr() is not acting on a copy of the caller's vector<Record>, leaving sortedRec holding dangling pointers when the copy is destroyed when dmaArr() exits:

void dmaArr(..., vector<Record> &records)

Then, you can and should replace one level of pointer indirection on sortedRec by using a reference instead of a pointer:

void dmaArr(Record** &sortedRec, vector<Record> records) {
    sortedRec = new Record *[records.size()];
    for (size_t i = 0; i < records.size(); ++i) {
        sortedRec[i] = &records[i];
        cout << sortedRec[i]->name << endl;
    }
    ...
}
vector<Record> records;
Record** sortedRecords;

// populate records as needed...

dmaArr(sortedRecords, records);

// use sortedRecords as needed...

delete [] sortedRecords;

Then, you can and should replace another level of pointer indirection on sortedRec by using std::vector instead of new[]. Let std::vector manage the dynamic memory for you, especially since the caller is already using std::vector anyway:

void dmaArr(vector<Record*> &sortedRec, vector<Record> &records) {
    sortedRec.resize(records.size());
    for (size_t i = 0; i < records.size(); ++i) {
        sortedRec[i] = &records[i];
        cout << sortedRec[i]->name << endl;
    }
    ...
}
vector<Record> records;
vector<Record*> sortedRecords;

// populate records as needed...

dmaArr(sortedRecords, records);

// use sortedRecords as needed...

Upvotes: 1

1201ProgramAlarm
1201ProgramAlarm

Reputation: 32732

In your cout statement, sortedRec[i] has type Record**, which you cannot use with the pointer dereference operator. You can use (*sortedRec[i])->name to get the name field of the record just assigned.

Incidentally, because you pass records by value, all the pointers stored in your for loop are to this temporary object and will be danging once the function returns. You should pass records by reference: vector<Record> &records to avoid that.

Upvotes: 2

Related Questions