C++ error:Assignment of read-only location - c++

Please help me to find the problem, I am totally lost why I can't modify my list. As you can see I did not declared anything as const..
Here is the code:
struct Carte
{
Carte(initializer_list<initializer_list<int>> iInp){}
initializer_list<initializer_list<int>> aVect;
};
.....
void changeValue(Carte& iCarte, int iValA, int iValB)
{
initializer_list<initializer_list<int>> carte = iCarte.aVect;
initializer_list<initializer_list<int> >::iterator carte_iterator;
initializer_list<int>::iterator carteRow_iterator;
//changing the value
int aLocalI = 0;
int aLocalJ = 0;
for(carte_iterator = carte.begin();carte_iterator!=carte.end();++carte_iterator)
{
if (aLocalI == iValA)
{
for(carteRow_iterator = (*carte_iterator).begin();carteRow_iterator!=(*carte_iterator).end();++carteRow_iterator)
{
if (aLocalJ == iValB)
{
*carteRow_iterator = 1; // ERROR HERE
}
aLocalJ++;
}
}
aLocalI++;
}
}
Many thanks in advance,
Julia

From http://en.cppreference.com/w/cpp/utility/initializer_list:
An object of type std::initializer_list<T> is a lightweight proxy object that provides access to an array of objects of type const T.
The elements of an initializer_list are always const, and thus *carteRow_iterator is const.
If you want a modifiable list of objects, use std::vector or std::array.

Related

Using pointer vector to reference vector is illegal?

I have one question.
Is it ok to use pointer vector as reference vector?
Struct Child
{
int n;
void func(int _n)
{
n = _n;
};
}
struct Parent
{
std::vector<Child> vec;
}
void func(Parent* p)
{
std::vector<Child>& ref = p->vec; // is this ok?
int value = 10;
ref[0].func(value); // is this ok?
}
int main()
{
...
...
Parent p;
func(&p);
...
...
return 0;
}
compiler gcc 4.4.7 (under c++11)
I guess, would it be okay if changed the value of the reference?
ref[0].func(value)
Thank you.
std::vector<Child>& ref = p->vec; // is this ok? yes
int value = 10;
ref->func(value); // is this ok? no
ref is not a pointer so you cannot use the member access operator ->
ref is a vector, so you need to pick which Child you want to use.
ref[ child_index ].func(value);
reference is nothing else but another name of an object. So these are all the same:
std::vector<Child>& ref = p->vec;
std::vector<Child>& vecAlias = ref;
int value = 10;
ref[0].func(value);
vecAlias[0].func(value);
p->vec[0].func(value);
You can't change a value of a reference. Uninitialized referenced don't exist. Once it's initialized there is no way of changing it.
Pointers on the other hand have similar purpose: they allow access to the same data from different places. You can always change what a pointer points to. But pointers are also more error-prone as then can be uninitialized or null-initialized. So try to stick to references if you don't need this flexibility.

c++ error: array initializer must be an initializer list

I have really been struggling with a piece of code for a couple days. The error message i receive when i run my code is:
error: array initializer must be an initializer list
accountStore (int size = 0) : accts(size) { }
There seem to be others with similar problems here but unfortunately I am unable to apply their solutions (either don't work or not applicable).
What I am simply attempting to do is create a container class (array, can't use vectors) of a class 'prepaidAccount' but I am just unable to get the constructor portion of the container class 'storeAccount' to work. See code snippet below:
class prepaidAccount{
public:
//prepaidAccount ();
prepaidAccount(string newPhoneNum, float newAvailBal) : phoneNumber(newPhoneNum), availableBalance (newAvailBal){} //constructor
double addBalance(double howMuch) {
availableBalance = howMuch + availableBalance;
return availableBalance;
}
double payForCall(int callDuration, double tariff) {
callDuration = callDuration/60; //convert to minutes
double costOfCall = callDuration * tariff;
if (costOfCall > availableBalance) {
return -1;
}
else {
availableBalance = availableBalance - costOfCall;
return costOfCall;
}
}
void setAvailBal(int newAvailBal) {availableBalance = newAvailBal;}
float getAvailBal() {return availableBalance;}
void setPhoneNum(string newPhoneNum) {phoneNumber = newPhoneNum;}
string getPhoneNum() const {return phoneNumber;}
private:
string phoneNumber;
float availableBalance;
};
class accountStore { //made to store 100 prepaid accounts
public:
accountStore (int size = 0) : accts(size) { }
....
private:
prepaidAccount accts[100];
}
In main I simply call accountStore Account;
Any help is absolutely welcome. I very recently started learning c++ and about classes and constructors so please bear with me.
Thanks
You can't initialize an array with int like accountStore (int size = 0) : accts(size) {}.
prepaidAccount doesn't have a default constructor, you have to write member initialization list like,
accountStore (int size = 0) : accts{prepaidAccount(...), prepaidAccount(...), ...} { }
The array has 100 elements, it's not a practical solution here.
As a suggestion, think about std::vector, which has a constructor constructing with the spicified count of elements with specified value. Such as,
class accountStore {
public:
accountStore (int size = 0) : accts(size, prepaidAccount(...)) { }
....
private:
std::vector<prepaidAccount> accts;
};
Given that you have specified that you do not want to use a container such as std::vector but would like to specify the size at runtime, your only option would be to manually implement dynamic allocation yourself. Also given that you are wanting create 100 objects at a time, I would suggest making a function that can construct a temporary object according to your needs and then use this to initialise your dynamically allocated array. Consider the below code as a good starting point. (WARNING untested code.)
class prepaidAccount {
public:
// Constructor
prepaidAccount(string newPhoneNum, float newAvailBal)
: phoneNumber(newPhoneNum), availableBalance(newAvailBal) {}
// Default Constructor needed for dynamic allocation.
prepaidAccount() {}
/* your code*/
};
// Used to construct a tempoary prepaid account for copying to the array.
// Could use whatever constructor you see fit.
prepaidAccount MakePrepaidAccount(/*some parameters*/) {
/* Some code to generate account */
return some_var;
}
class accountStore {
public:
// Explicit constructor to avoid implicit type-casts.
explicit accountStore(const int &size = 0)
: accts(new prepaidAccount[size]) {
for (int i = 0; i < size; i++) {
// Will call defualt assignment function.
prepaidAccount[i] = MakePrepaidAccount(/*some parameters*/);
}
}
// Destructor
~accountStore() {
// Cleans up dynamically allocated memory.
delete[] prepaidAccount;
}
prepaidAccount *accts;
};
Edit: Amongst the c++ community it is often questionable when choosing to use dynamic allocation when there is such an excellent and comprehensive library of smart pointers. For example an std::vector would be perfect in this situation.

Dynamic Polymorphic Memory Container - Return Value Incorrect

I am currently working on an dynamic memory container.
Basic idea of the class is that you should be able to get the iterator of an object if you really do not know it, without the use of a for loop throughout all the elements to boost performance. The issue I have is the following; when you pass your pointer address to the object you want to get the iterator of it type casts the object into the extended memory containers structures type. This type contains an extra element, an integer. (IteratorNum)
When following the code the integer within the function is set to correct value, as below would be 50. But when the returned value is set into the local integer used in the main function it is 200? I've been adding watches and cannot figure out how it is possible that the function returns 50 but value gets set to 200.
template <typename DataType> class MemoryContainer {
public:
struct LevelData : DataType
{
int element;
};
DataType &New()
{
elements++;
//Reallocate the size of the array
ld = (LevelData*)realloc(ld, sizeof(LevelData) * elements);
//Set the iteratorNumber
ld[elements - 1].element = elements - 1;
return ld[elements - 1];
}
DataType *reserve(int num)
{
return calloc(num, sizeof(DataType));
}
DataType &operator[](int i)
{
return ld[i];
}
bool inArray(DataType *type)
{
//Compare memory addresses and see if it's within.
return (type >= &ld[0]) && (type < &ld[elements - 1]);
}
static unsigned int getIterator(DataType *type)
{
// v this is 50, but in main says returns 200.
return ((LevelData*)type)->element;
}
MemoryContainer()
{
elements = 0;
}
~MemoryContainer()
{
free(data);
}
private:
unsigned int elements;
LevelData *ld;
};
struct Effective
{
//Set it to polymorphic classes
virtual void dummy()
{
}
char * testvar;
Effective(char * c)
{
testvar = c;
}
Effective(){}
};
MemoryContainer<Effective> myContainer;
int _tmain(int argc, _TCHAR* argv[])
{
//Create 200 elements in the array
for(int i = 0; i < 200; i++)
myContainer.New().testvar = "E";
//Add pointer for testing purposes to get the iterator.
Effective * pointer = &myContainer[50];
//Test setting it's value
pointer->testvar = "HEHEHE";
//Get iterator of our pointer in the array
unsigned int i = myContainer.getIterator(pointer);
printf(pointer->testvar);
system("PAUSE");
return 0;
}
I suspect it is the visual studio debugger getting confused between your two i variables. If you print out the value of i, it will print correctly. If you change the name of your variable to something else, the value shows as 50 in the debugger.
That said, your code is a mish-mash of c and c++ and won't work correctly with anything that requires a copy constructor. I would suggest at the very least using new [] rather than realloc.
Also, any user of this collection who tries to store a class with a member variable called element is going to get mighty confused.
The unsigned int i in the main function really has a value of 50, but the debugger is confusing it with the i declared in the for loop (I reproduced this with Visual Studio 2013). If you cout i it will be 50, and if you change the variable name it will show up as 50 in the debugger. I've never seen this problem before so I wonder if it might be due to your use of malloc/realloc/free with C++ objects.

class constructor with structure array (direct)

UPDATE:
i see im causing much confusion in here, sry bout that guys.. thanks Roman for the idea with the vectors ^^
clarifing my problem: i want to get the structure-array straigth into the created class (in main()) by passing the integers as an parameter(i dont want to create global or local variables for dem arrays) and copying them into the class-member
the problem is im failing at the initialization of the class, my attempt:
struct _Note
{
int nFrequenz;
int nTakt;
};
class _Chart
{
public:
_Chart( std::vector<_Note> vNotes )
{
for( int i = 0; i < vNotes.size(); i++ )
this->_chart.push_back( vNotes[i] );
}
private:
std::vector<_Note> _chart;
};
void main()
{
_Chart x(
{ {1,2}, {2,3} }
);
// not working, wrong initialization
// still confused about the brackets ^^
getchar();
}
When passed as a parameter struktur p[] decays to a pointer (similar to struktur* p). The size of this pointer will definitely not be what you're looking for in determining the number of elements.
Instead, why not provide a two iterator constructor similar to the standard containers?
You need to pass the element count too:
klasse( struktur p[], size_t count )
{
_chart = new struktur[count];
// copy array in one shot as no deep copy is needed here.
memcpy(_chart, p, count * sizeof(struktur));
}
An array decays to a pointer when passed. So, you must pass the count of elements in the array as an additional parameter to the function. However, in this scenario, you have an option.
Move the glob definition to above the klasse declaration. Then in the constructor you should be able to get the count of objects with sizeof(glob)/sizeof(struktur);. You should be able to dynamic allocate and do a member wise copy there after.
Why not to use the std::vector container template?
class klasse
{
public:
klasse(std::vector<struktur>& strs)
{
_chart = new struktur[strs.size()];
for( int i = 0; i < strs.size(); i++ )
{
this->_chart[i] = strs[i];
}
}
private:
struktur* _chart;
};
And in main():
void main()
{
std::vector<struktur> myStructs;
myStruct.push_back(glob[0]);
myStruct.push_back(glob[1]);
myStruct.push_back(glob[2]);
klasse y(myStructs);
getchar();
}
This is simple and elegant.
[Upd.] Yes, here in your example sizeof(p) will be equals to sizeof(uintptr_t) because p is a pointer type.

Problem passing a list of objects to another class, C++

Below I have written a sample program that I have written to learn about passing a list of objects to another class. I talk about the problems I am having below.
#include <iostream>
#include <vector>
using namespace std;
class Integer_Class
{
int var;
public:
Integer_Class(const int& varin) : var(varin) {}
int get_var() { return var; }
};
class Contains_List
{
typedef Integer_Class* Integer_Class_Star;
Integer_Class_Star list;
public:
Contains_List(const Integer_Class_Star& listin) : list(listin) {}
Integer_Class* get_list() { return list; }
};
int main (int argc, char * const argv[])
{
// Create a vector to contain a list of integers.
vector<Integer_Class> list;
for(int i = 0; i < 10; i++)
{
Integer_Class temp_int(i);
list.push_back(temp_int);
}
This is where the errors start occuring. Could someone please look at the second class definition and the code below and shed some light on what I'm doing wrong. Thank you so much, as always!
// Import this list as an object into another object.
Contains_List final(list);
// Output the elements of the list by accessing it through the secondary object.
for(int i = 0; i < 10; i++)
{
cout << final.get_list()[i].get_var();
}
return 0;
}
You don't mention what sort of errors you are getting, but one very obvious problem with your code is that the constructor for Contains_List expects a pointer to Integer_Class while the parameter you are sending it (list) is of type vector<Integer_Class>.
A vector is not the same as an array, so you cannot pass it as pointer to the type it contains. Either change your constructor to accept a vector or pointer/reference to vector, or change the code that is causing you problems so that it sends it a pointer to an array.
The 'Contains_List' constructor takes in an 'Integer_Class*'
You declare 'list' to be of type 'vector', yet you pass it to the the 'Contians_List' constructor. You should change the 'Contains_List' class so that it holds a vector instead of an Integer_List array. The two are not interchangeable.
You could also change the vector to be an array of Integer_List's instead, if you so wished.