I am new to the pointer usage and encountered a compiling error gcc
Here is my code:
class Pt
{
public:
int Ph;
};
Pt *Pa;
Pa = new T[N];
for(int i=0;i < N; i++)
Pa[i].Ph=0;`
and the error message:
error: expected type-specifier before ‘T’
error: cannot convert ‘int*’ to ‘Pt*’ in assignment
What I am trying to do is to declare a class which contains an int which is 0 initially ,and provide a mem space to N of that class.
Thanks for the time reading my questions,any help will be very appreciated.
Without a user-defined constructor, you can value-initialize an object like so:
Pt a = Pt();
a is an object of type Pt with its int member set to 0.
To declare an array, use:
Pt* Pa = new Pt[N]();
The N objects in the array are value-initialized, so the following for loop is no longer necessary.
To write C++ code, just do
std::vector<Pt> Pa(N);
You did not declare any type called T; probably you have other errors/warnings before that complain about that.
You have multiple mistakes
1) Pa[i] would hold a pointer to pt. so consider writing Pa[i]->Ph
2) What you want to do here is not clear:
Pa = new T[N];
Try something like this:
class Pt
{
public:
Pt() : Ph(0)
{ ; }
int Ph;
};
#define CAPCITY 15U
int main(void)
{
Pt Pa[CAPACITY];
for (unsigned i = 0; i < CAPACITY; ++i)
{
std::cout << "Pa[" << i << "].Ph = " << Pa[i].Ph << endl;
}
return EXIT_SUCCESS;
}
The initializer list of class Pt handles setting the field Ph to zero when the class is constructed by the array.
BTW, you don't need to use new for each variable instance, unlike other languages.
I highly recommend using more letters for your class and variable names and try to use something meaningful. Two letters are faster to type, but if that is your justification, take a keyboarding class.
Related
int main()
{
int j;
std::cin >> i >> j;
int (**ptr)[1];
ptr = new (int*[i][1]);//error
for (int index = 0;index < i;++index)
ptr[index] = new (int[j][1]);
}
I have a compiler error.
Then, how can I allocate int(**)[]?
Problem.
Original code except that I've added the missing #include directive – to avoid wrong guesses about your code, and irrelevant issues being discussed, please do include everything in posted code:
#include <iostream>
int main()
{
int j;
std::cin >> i >> j;
int (**ptr)[1];
ptr = new (int*[i][1]);//error
for (int index = 0;index < i;++index)
ptr[index] = new (int[j][1]);
}
Compiling with MinGW g++ 5.1.0:
C:\my\forums\so\116> g++ --version | find "++"
g++ (tdm64-1) 5.1.0
C:\my\forums\so\116> g++ original.cpp
original.cpp: In function 'int main()':
original.cpp:5:17: error: 'i' was not declared in this scope
std::cin >> i >> j;
^
original.cpp:9:35: error: ISO C++ forbids variable length array [-Wvla]
ptr[index] = new (int[j][1]);
^
original.cpp:9:36: error: non-constant array new length must be specified without parentheses around the type-id [-Wvla]
ptr[index] = new (int[j][1]);
^
C:\my\forums\so\116> _
That compiler detected the following problems:
Missing declaration of variable i.
Inadvertent use of C99 variable length array, VLA, due to syntactical error.
Compiling with Visual C++ 2015 update 2:
C:\my\forums\so\116> cl /nologo- 2>&1 | find "++"
Microsoft (R) C/C++ Optimizing Compiler Version 19.00.23725 for x86
C:\my\forums\so\116> cl original.cpp
original.cpp
original.cpp(5): error C2065: 'i': undeclared identifier
original.cpp(7): error C2065: 'i': undeclared identifier
original.cpp(7): error C2440: '=': cannot convert from 'int *(*)[1]' to 'int (**)[1]'
original.cpp(7): note: Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
original.cpp(8): error C2065: 'i': undeclared identifier
C:\my\forums\so\116> _
This compiler doesn't support C99 VLAs, and so instead diagnoses
Incompatible types in pointer assignment.
Apparently this is the error message the OP is concerned about, but the OP reported it as
” cannot cast int ()[] to int(**)[]
which is meaningless because one can indeed cast between data pointer types.
So,
The error description in the question is incorrect.
The code has issues (lacking include, lacking variable declaration) in addition to the error singled out by the OP.
It's unclear what the code is meant to do, except in a very abstract sense that allowed advice such as “use a std::vector”.
However, the code snippet
for (int index = 0;index < i;++index)
ptr[index] = new (int[j][1]);
strongly indicates that this is an attempt to do a dynamic size matrix (2D array) of int values, with dimensions specified by the user, and I assume that in the following.
Fix of the original code.
It often helps to name things. In this case, for clarity, we can name the int* type as Int_array_ptr. That indicates the intended usage: not as a pointer to a single int, but as a pointer to the first item of an array of int, i.e. as a pointer to the array.
#include <iostream>
int main()
{
int n_rows;
int n_columns;
std::cin >> n_rows >> n_columns;
using Int_array_ptr = int*;
Int_array_ptr* matrix;
matrix = new Int_array_ptr[n_rows]; // An array of `n_rows` pointers.
for( int i = 0; i < n_rows; ++i )
{
matrix[i] = new int[n_columns](); // The `()` adds zero-initialization.
}
// At this point one can use it like `matrix[row][column] = 42`.
}
The resulting structure is called a jagged array, because it permits the column vectors to be of different lengths (here they're all the same length).
How to do a matrix in general.
A good alternative to matrix-as-jagged-array is to use a single contiguous 1D array as storage, and just provide 2D indexing into this array.
A good to way to manage an array's storage is to use a std::vector.
And a good way to encapsulate an indexing operation plus other array stuff (or most any set of related operations on a common state) is to define a class.
So, this strongly suggests to define a class that provides a 2D indexing operation on a single 1D array whose storage is managed by a std::vector.
The indexing would ideally be via operator[], but as a member operation it can only take 1 argument. And it's a bit of a bother to write e.g. matrix[Location(3,58)] instead of the ideal matrix[3,58] (which would be parsed as use of a comma expression). So, typically operator(), the function call operator, is used instead of [].
It's possible to instead support the notation matrix[3][58], but let's choose the conceptually simpler implementation of operator():
#include <iostream>
#include <vector>
#include <stdlib.h> // EXIT_FAILURE
using namespace std;
class Matrix
{
private:
vector<int> items_;
int n_columns_;
auto index_of( int const row, int const col ) const
-> int
{ return row*n_columns_ + col; }
public:
auto operator()( int const row, int const col )
-> int&
{ return items_[index_of( row, col )]; }
auto operator()( int const row, int const col ) const
-> int
{ return items_[index_of( row, col )]; }
Matrix( int const n_rows, int const n_columns )
: items_( n_rows*n_columns )
, n_columns_( n_columns )
{}
};
auto main() -> int
{
int n_rows;
int n_columns;
std::cin >> n_rows >> n_columns;
if( cin.fail() ) { return EXIT_FAILURE; }
Matrix matrix( n_rows, n_columns );
// At this point one can use it like `matrix( row, column ) = 42`.
}
This is far more code than the original, but
it's reusable code, which saves work,
it's more robust code, with the difficult things (memory management) automated, and
it can even be more efficient, because it manages with a single dynamic allocation.
Seems like you want to allocate 2-D array. So the allocation should be done as:
int i, j; // Initialize some value to i, j.
....
int **ptr = new int*[i];
for(int k = 0; k < i; k++) {
ptr[k] = new int[j];
}
This will make a 2-D array that has i rows and j columns.
You are trying to allocate an array of int (*)[1] objects. You've already noticed that syntax like new int(*)[1] doesn't work because it is parsed as new int followed by the function call operator, so you have to use the new(T) form.
Also, int *[i][1] is not right, because int * is pointer-to-int. Much like you did in int (**ptr)[1], you have to use parentheses to break the * from the int.
So the right syntax for this would be new( int (*[i])[1] ). But unfortunately, the new(T) form is not allowed to contain non-constant expressions inside the parentheses!
Technical information: There is a dedicated grammar (C++14 [dcl.name]/1) for the cases sizeof(T), alignof(T), new(T) and typeid(T) and casts; and it only permits square brackets to be empty or contain a constant-expression inside the square brackets. There is another separate grammar for the new T case ([expr.new]/1) (which knows about [] but not (), and allows non-constant expressions), and both of these are separate to the grammar for parsing declarators in other situations.
So the only solution to this (while retaining the type of ptr) is to use a typedef:
typedef int Arr1[1];
ptr = new Arr1 *[i];
Each row is:
ptr[index] = new int[j][1]; // or "new Arr1[j];"
you have allocate an pointer array, and then each element(pointer) points to an array like
int i = 20, j = 40;
int** ptr = new int*[i];
for (int a = 0; a < i; a++) {
ptr[a] = new int[j];
// ...
delete [] ptr[a];
}
delete [] ptr;
EDIT
back to your code
when you define a type E as int[1];
int j, i;
std::cin >> i >> j;
typedef int E[1];
E **ptr; // int (**ptr)[1];
ptr = new E*[i]; // ptr = new (int*[i][1]);//error
for (int index = 0;index < i;++index)
ptr[index] = new E[j]; // ptr[index] = new (int[j][1]);
so just a pointer to pointer of integer, not like what you said
I wrote a simple piece of C++ code to pass addresses by reference.
I am passing the address of a variable (say y) and an array (say arr) to a class. Both arr and y will get modified inside the class. I want to have the modified values in my main().
Please find my question in the below piece of code as it is easier that way. Thanks.
#include <iostream>
using namespace std;
class A
{
public:
// Assign values to the array and increment _x.
void increment()
{
(*_x)++;
(*_arr)[0] = 1; // Q1. Is it safe to directly access the array like this.
(*_arr)[1] = 2; // Don't I have to allocate memory to the array ?
(*_arr)[2] = 3;
}
// Get the address of the Variable that is passed in main. x will now have &y2.
A (int* &arr, int* &x):
_x(x)
{
*_arr = arr;
}
private:
int* _x;
int** _arr;
};
int main()
{
int y = 9;
int arr[5];
int *pY = &y;
int *pArr = arr;
A *obj1 = new A(pArr, pY);
// This gives a compile time error. warning: initialization of non-const reference int *&' from rvalue `int *'
// A *obj1 = new A(&y); <-- Q2. Why does this give a Compile Time Error ?
obj1->increment();
cout << "y : " << y << endl;
cout << "[0]: " << arr[0] << "; [1]: " << arr[1] << "; [2]: " << arr[2] << endl;
cout << endl;
return 0;
}
In A::increment() function, I am directly assigning values to the array without
allocating memory. Is it safe to do ? If not, how can I allocate memory so that
I can still get the modified array values in main() ?
Why do I get a compile time error whey I pass &y to A's constructor ?
Thanks in advance.
Question 1
In A::increment() function, I am directly assigning values to the array without allocating memory. Is it safe to do ? If not, how can I allocate memory so that I can still get the modified array values in main() ?
Answer
Yes, it is safe.
Question 2
Why do I get a compile time error whey I pass &y to A's constructor ?
Answer
&y is not an lvalue. Hence, it cannot be used where the argument type is int*&.
Problem in posted code
*_arr = arr;
That is a problem since _arr has not been initialized to point to a valid memory. Using *_arr when _arr has not been initialized causes undefined behavior. You can change the type of _arr to:
int* _arr;
and simplify your code a little bit.
class A
{
public:
// Assign values to the array and increment _x.
void increment()
{
(*_x)++;
_arr[0] = 1; // Q1. Is it safe to directly access the array like this.
_arr[1] = 2; // Don't I have to allocate memory to the array ?
_arr[2] = 3;
}
// Get the address of the Variable that is passed in main. x will now have &y2.
A (int* &arr, int* &x):
_x(x),
_arr(arr)
{
}
private:
int* _x;
int* _arr;
};
without changing anything in main.
This is very rarely what you want; a T** is generally an array of arrays or else a pointer value that you want to modify in the caller’s scope. However, neither seems to be what you’re doing here.
It is safe to modify *_arr[0] if and only if _arr has been initialized to a array of non-const arrays, and (*_arr)[0] if and only if it has been initialized as a pointer to a non-const array. Neither appears to be the case here, but if it is, you probably want to give the array length explicitly.
In this example, &y is a constant. You can’t modify it, so you can’t pass it as a non-const variable. You can declare a pointer int *py = &y; and pass that. But consider whether that’s what you want to do.
By the way, it’s not good style to use identifiers that start with underscores, because by the standard, they’re reserved for the compiler to use.
You should tell us what you are trying to do. In my opinion it's nonsense using raw pointers/arrays and naked new/(missing?) delete in C++ without good reason. I would also like to note that it is not considered good practice using the _prefix for class members. Usually leading _ are used for std implementations. I recommend using m_prefix if you insist on one. And why do you give _arr the type int**? Is is supposed to be a 2D-Array? Additionally, it doesn't really make sense passing a pointer by reference. A pointer is already a pointer, if you know what I mean, just pass the pointer around.
I'm just going to assume that you are doing this to understand manual memory management or pointer arithmetics or - wait, right: Tell us what you are trying to do and why. Nevertheless, I don't understand what you have the class for:
#include <iostream>
void increment(int& x, int *arr, int sz)
{
++x;
for (int i = 0; i != sz; ++i)
{
// this just numbers the values respectively (starting at 1)
arr[i] = i + 1;
}
}
int main()
{
using namespace std;
int y = 9;
const int sz = 5;
int arr[sz];
increment(y, arr, sz);
cout << "y : " << y << '\n'
<< "[0]: " << arr[0] << "; [1]: " << arr[1] << "; [2]: " << arr[2] << "\n\n";
}
To answer your questions:
2. First thing first: I don't see any constructor that only takes one argument.
Read up on "Undefined Behaviour (UB)" starting point: What are all the common undefined behaviours that a C++ programmer should know about?
I can't repeat enough that I don't understand what you are going for and that makes it hard to give solid advice.
I tried fixing your version.. well its still terrible... I highly recommend on reading up on std::array, std::vector. Maybe on pointers, C-Style Arrays and how to pass C-Style Arrays as function arguments (note: for regular C++ programming you wouldn't be doing/using that, usually).
#include <iostream>
class A {
public:
// Assign values to the array and increment m_x.
void increment()
{
++(*m_x);
m_arr[0] = 1;
m_arr[1] = 2;
m_arr[2] = 3;
}
A (int* arr, int* x):
m_x(x), m_arr(arr)
{
}
private:
int* m_x;
int* m_arr;
};
int main()
{
using namespace std;
int y = 9;
int arr[5];
A obj1(arr, &y);
obj1.increment();
cout << "y : " << y << '\n'
<< "[0]: " << arr[0] << "; [1]: " << arr[1] << "; [2]: " << arr[2] << "\n\n";
A obj2(arr, &y);
obj2.increment();
cout << "y : " << y << '\n'
<< "[0]: " << arr[0] << "; [1]: " << arr[1] << "; [2]: " << arr[2] << "\n\n";
}
You should also read up un pointers/references and their differences
I am actually trying to make your programming life easier. Sorry for long answer.
In answer to your first question
In A::increment() function, I am directly assigning values to the
array without allocating memory. Is it safe to do ? If not, how can I
allocate memory so that I can still get the modified array values in
main() ?
you allocated memory in main(), in the line
int arr[5];
In terms of class design, you defined your class constructor to accept reference arguments, which means that an existing int* must be passed to each argument:
A (int* &arr, int* &x)
and you do so when you invoke the constructor:
A *obj1 = new A(pArr, pY);
so in this program, what you are doing is safe. A potential danger if you expect to use this class in another context would be if your arr array in main() contained fewer than 3 elements, since your increment() function initializes the third element of the array.
In answer to your second question
Why do I get a compile time error whey I pass &y to A's constructor ?
In your original constructor,
// Get the address of the Variable that is passed in main. x will now have &y2.
A (int* &arr, int* &x):
_x(x)
{
*_arr = arr;
}
you are dereferencing _arr before it has been initialized. One way to solve this would be to do this:
// Get the address of the Variable that is passed in main. x will now have &y2.
A (int* &arr, int* &x):
_x(x)
{
_arr = new (int*);
*_arr = arr;
}
// Destructor
~A ()
{
delete _arr;
}
As an aside, you also use new in main(). Whenever you use new, you should also use delete to avoid a memory leak. So at the bottom of your program, before the return statement, add the following:
delete obj1;
I read code of mysql source code in line 148, source code link here
I got confused here:
typename List::node_type& elem_node = elem->*list.node;
It's so strange: ->*.
What's the grammar meaning?
The ->* notation is needed because list is a pointer to a member. Here's a simple example:
#include <iostream>
struct S {
int a;
int b;
};
int main()
{
// 'ptr' now points to the 'b' member of some 'S' value.
int (S::*ptr) = &S::b;
S *x = new S;
x->*ptr = 5;
std::cout << x->b << '\n';
}
This program prints '5'. The ptr pointer is made to be of type int (S::*), i.e. a pointer to some int member of a S struct. It's initialized to point to the b member.
Of course, to actually do something sensible with it you need to specify which S struct to modify. That's done via
x->*ptr
Which can be read as "the member of the x value which is dereferenced by the ptr pointer".
Currently I have a several classes with an array defined as 'float myIDs'. I want to move the variable into my parent class and change it to a pointer ('float * myIDs').
Currently I'm declaring its values like this:
float myIDs[] = {
//Variables
};
As its now a pointer, I thought that it would be roughly the same:
myIDs = new float[] = {
};
but that doesnt seem to be working. I'm not sure how to solve this as I've never had to declare a pointer array like this before.
Can anyone help me please?
Thanks
Note that you're not allocating an array of pointer but just an array of float, so basically you two array would have the same type, they just won't be stored in the same memory space.
Only a statically allocated array can be initialized this way, a dynamically allocated one cannot be initialized to anything other than zero.
myIDs = new float[]();
But if you know the elements to put in the array, you don't need to allocate it dynamically.
If you want to allocate an array of pointer, you have to do this :
float* myIDs[size]; // statically
float** myIDs = new float*[size]; // dynamically
But only the statically allocated one (the first one) can be initialized the way you describe and of course, it must be initialized with pointers.
If you want to declare array in a dynamic way, you can do it like this:
float *array = new float[size];
array[0] = first_value;
array[1] = second_value;
etc;
Just remember to free memory when you no longer need it (e.g. in a class destructor)
delete [] array;
If you want a dynamically allocated array you should use the following format (what you did seems more like C# not C++)
//The declaration of the object in the class
float *myIDs;
//The allocation it self (you must know which size you want to allocate at this point)
myIDs = new float[size];//bring change "size" to whatever you need is.
Consider the following snippet,
#include<iostream>
#include<stdlib.h>
int main(void)
{
int a[] = {1,2};
a =new int[2];
delete(a);
return 0;
}
This gives an error error: incompatible types in assignment of ‘int*’ to ‘int [2]’.
I am statically creating an array of int . a is a pointer(it is of type int[2]) but it can't be used to point to other dynamically allocated arrays because they return pointer of type int*.
If you want to create an array dynamically you have to assign its address to a float*
float * a = new float[10] ;
Refer this too.
The easiest way is:
float *myArray[size];
Example
#include <iostream>
using namespace std;
float* findMax (float* myArray[], int size) {
float max = 0;
int index = 0;
for (int i = 0; i < size; i++) {
if ( *myArray[i] > max) {
max = *myArray[i];
index = i;
}
}
return myArray[index];
}
int main()
{
float a = 1.25;
float b = 2.47;
float c = 3.92;
float d = 4.67;
float e = 5.89;
float f = 6.01;
float *myArray[6];
int len = *(&myArray + 1) - myArray;
myArray[0] = &a;
myArray[1] = &b;
myArray[2] = &c;
myArray[3] = &d;
myArray[4] = &e;
myArray[5] = &f;
cout << "Number of even values are : " << findMax(myArray, len) << endl;
return 0;
}
If you want an array of pointers to float, you must declare it as such. You declared just an array of floats. The name of the array is a pointer of course, but in the C sytnax it is treated the same and just a convenience.
float *myIDs[] = {
//Variables
};
myIDs = new *float[n] = {
};
Alternatively you can use
float **myIDs;
myIDs = new **float;
And access it the same way like an array:
float *x = myIDs[i];
I have quite peculiar problem. I want initialize an array pointed by a void pointer to which memory is allocated using new as shown below.
const int ARRAY_SIZE = 10;
void InitArray()
{
int *ptrInt = new int[ARRAY_SIZE];
for(int i=0; i<ARRAY_SIZE;i++)
{
ptrInt[i] = 1; //OK
}
void *ptrVoid = new int[ARRAY_SIZE];
for(int i=0; i<ARRAY_SIZE;i++)
{
*(int*)ptrVoid[i] = 1; //Culprit : I get a compiler error here
//(error C2036: 'void *' : unknown size)
}
}
Now, I want to initialize the elements of this array which is pointed by ptrVoid with say 1. How do I go about it? With this code I get a compiler error as shown in the code(I am using VS 2010). Any suggestions?
You have an order of operations problem (and an extra *). Try this inside your second loop:
((int *)ptrVoid)[i] = 1;
*(int*)ptrVoid[i] is *((int*)(ptrVoid[i])), and you're dereferencing too many times (the [] does a dereference).
Write ((int*)ptrVoid)[i] (or, better, static_cast<int*>(ptrVoid)[i]) then re-consider your use of void* at all.
You just need to parenthesize correctly and cast the void* to an int*, so that the compiler knows how many bytes to offset when you index it with [i].
for(int i=0; i<ARRAY_SIZE;i++)
{
((int*)ptrVoid)[i] = 1;
}
How about:
int* ptrVoidAsInt = new int[ARRAY_SIZE];
for(int i=0; i<ARRAY_SIZE;i++)
{
ptrVoidAsInt[i] = 1;
}
void* ptrVoid = ptrVoidAsInt;
But, one has to wonder what the meaning of either a void array or 1 initialised data is. Is this really an array of int or some other type that is going to be passed as a void* and then recast back to a typed array?