When trying to compile code g++ gives me this error: 'array must be initialized with a brace-enclosed initializer'
#include<iostream>
int main(){
int coordinates[3][2]={{1,2},
{5,2},
{5,9}};
for(int coordinate[2]:coordinates){
std::cout<<coordinate[0]+coordinate[1];
};
return 0;
};
Well, I can clearly see a problem in your code.
In loop, type is not plain int, but int*. You have two options, either use int* or auto
Your final code should look line
int main(){
int coordinates[3][2]=
{
{1,2},
{5,2},
{5,9}
};
// You can use either int* or auto.
// I personally prefer auto
// as it's more cleaner.
//
// for(int *coordinate :coordinates){
for(auto coordinate:coordinates){
std::cout<<coordinate[0]+coordinate[1];
};
return 0;
};
Related
Code-1
#include <iostream>
#include <cstring>
class A
{
private:
int p[5];
char str[20];
public:
A(int *q, char *s)
{
for(int i=0; i<=4; i++)
{
p[i]=*q;
q++;
}
strcpy(str,s);
}
};
int main()
{
int r[5]={2, 3, 5, 7, 11};
char ch[]="bonaparte";
A a1(r, ch);
return 0;
}
Output ( Runs smoothly but just gives warning )
Clang-Tidy: Constructor does not initialize
these fields: p, str
Why this warning is coming. I know that I am assigning in constructor not initializing but When I create simple class which just have int type variable and If I assign that in this same way it didn't give such warning ?
Code-2
#include <iostream>
#include <cstring>
class A
{
private:
int p[5];
char str[20];
public:
A(int *q, char *s): // just not getting how we can do this initialization
{
}
};
int main()
{
int r[5]={2, 3, 5, 7, 11};
char ch[]="bonaparte";
A a1(r, ch);
return 0;
}
Is there any way to initialize int type or C-style char array via member initialization list through constructor.
I know that I can replace char array with string but I want to know a way for C-style char array.
Arrays in C++ are not the friendliest bit of the language.
Specialy not when you let them decay to pointers (size information is lost).
So I prefer to use std::array, std::vector and std::string since these standard library classes help you prevent all sort of memory bugs.
About your initialization question, yes you can only assign in the body of the constructor. This is another reason I like std::array/std::vector better you can use them in the initializer. I also consider ::strcpy to be a left over from 'C' not to be used anymore in current C++. Have fun learning more C++ :)
#include <iostream>
//#include <cstring> // <== don't use this. (If you want to use strings in C++ use <string>
#include <vector>
#include <string>
// try to learn not to use what is called
// "magic numbers" in your source code!
// define numbers you are going to use
//
const std::size_t int_array_size = 5;
const std::size_t string_array_size = 20;
// we don't know the length of the string yet, but we can let
// the compiler figure it out and we make a templated constructor
class A
{
public:
// pass arrays in by const, you're not supposed to
// change their content.
A(const int (&p)[int_array_size], const char (&str)[string_array_size])
{
// I always use std::size_t for indices in arrays (not supposed to be <0)
for (/*int*/ std::size_t i = 0; i < int_array_size; i++) m_p[i] = p[i];
// don't use ::strcpy it's not "safe". It depends on correct input
// like the string having a trailing 0
for (std::size_t i = 0; i < string_array_size; i++) m_str[i] = str[i];
}
private:
int m_p[int_array_size];
char m_str[string_array_size];
};
// this is one way I would code it.
// using C++ with variable length array (so I use std::vector, for fixed length use std::array)
class B
{
public:
B(const std::vector<int>& p, const std::string& str) :
m_p{ p },
m_str{ str }
{
}
private:
std::vector<int> m_p; // or std::array<int,int_array_size>
std::string m_str;
};
int main()
{
// I prefer to use aggregate initialization (https://en.cppreference.com/w/cpp/language/aggregate_initialization)
int r[int_array_size]{ 2, 3, 5, 7, 11 };
// The next line is defined behavior. C++ standard says all remaining
// values of ch after bonaparte will be 0
char ch[string_array_size]{ "bonaparte" };
A a1(r, ch);
B b1{ {1,2,3}, "hello world!" };
return 0;
}
I have to do a function in c++ that returns 2 arrays by passing them from reference.
I have no idea and it seems noone also has.
Would you be so kind to write an exemple for me?
I thaught to do
int *vettore=new int[5];
return vettore
buy it only returns one.
Tnx in advance.
Let's forget about arrays for a second, because that is another bag of problems. Let's concentrate on returning two simple types, e.g. returning two integers.
Obviously this won't work (because... not python):
int, int foo()
{
int a = ...
int b = ...
return a, b;
}
So what options are you left with if you want to return multiple values in C++?
Option 1. Return a class
You can "bundle" your values in a class, either create a new class for them if that makes sense, or simply use std::pair or std::tuple:
std::pair<int, int> foo()
{
int a = ...;
int b = ...;
return {a, b}
}
Option 2. Use "out" parameters.
You can pass parameters by reference, thus being able to modify from within the function objects from outside. E.g.:
void foo(int& a, int& b)
{
a = ...;
b = ...;
}
I think this is what you teacher meant by "pass by reference".
Ok, what about arrays?
This is tricky to answer because it is not clear what you mean by arrays and some of the meanings are discouraged.
I will start from the most recommended, to what is considered bad practice and even wrong:
std::vector
The defacto type for representing arrays in C++ should always be std::vector. Thus your requirement of returning by reference could mean:
void foo(std::vector<int>& v1, std::vector<int&>& v2);
std::array
Alternately if the size of the array is known at compile time:
void foo(std::array<int, 24>& a1, std::array<int, 24>& a2);
C pointers
Ok, now we are in the discouraged territory. Don't do this, unless to appease an unreasonable teacher or curriculum:
void foo(int* &v1, int* &v2)
{
v1 = new int[11];
v2 = new int[24];
...
}
C arrays
void foo(int (&a)[11], int (&a2)[24]);
You could do this:
return std::make_pair(array1,array2);
You'll need to #include <utility>
To access the arrays use pair.first or pair.second
example:
#include <utility> //std::pair
#include <iostream> //std::cout
std::pair<int*,int*> returnpair(){
int arr1[3] = {1,2,3};
int arr2[3] = {4,5,6};
return std::make_pair(arr1,arr2);
}
int main(){
std::pair<int*,int*> pair= returnpair();
std::cout<<pair.first[1]; //access 2nd member of arr1
}
Output:
2
Reference:
http://www.cplusplus.com/reference/utility/pair/
You can do that by returning a struct node pointer which is acceptable in C/C++.
Following is the sample code of node :
struct node {
int a[100];
int b[100];
};
Coming to the function :
struct node* fun() {
struct node* ptr;
// write your code
return ptr;
}
In main : you can access the arrays as follows :
struct node* ptr=fun();
ptr->a // is the first array
ptr->b // is the second array
Hope it helps
Error: braces around scalar initializer for type int*
I'm trying to pass an array to the function but I keep getting this error in the initialization step.
How can I fix this?
#include <iostream>
using namespace std;
void func (int *p[4]);
int main()
{
int *p[4]={ {1,4,5},{3,5,6},{6,6,2},{6,5,3}}; //The error appears here
func(p);
return 0;
}
void func (int *p[4])
{
for(int i=0;i<4;i++)
{
for(int j=0;j<1;j++)
{ cout<<p[i][j]; }
}
cout<<" \t";
}
Problem is what is p.
Whit this definition:
int *p[4];
this is 4 element array of pointers to int.
I guessing you wanted this:
int (*p)[3];
pointer to 3 element array of ints.
Also to use initialization you need an array.
Here is working example.
The variable p is an array of pointers. { 1, 4, 5 } is not a pointer.
You need to make p an array of arrays:
int p[4][3] = { ... };
Because of that change, you have to change the func function argument as well, as p will now decay to a pointer to an array, of type int (*)[3] (that is, the argument for func should be int (*p)[3]).
This would work, however you are going to lose array information because they will decay into pointers:
int arr1[] = { 1,4,5 };
int arr2[] = { 3,5,6 };
int arr3[] = { 6,6,2 };
int arr4[] = { 6,5,3 };
int *p[4] = { arr1, arr2, arr3, arr4 };
I have a class like this
class aClass
{
public:
aClass() : N(5) {}
void aMemberFunction()
{
int nums[N] = {1,2,3,4,5};
}
private:
const int N;
};
The testing code is
int main()
{
aClass A;
A.aMemberFunction();
const int N = 5;
int ints[N] = {5,4,3,2,1};
return 0;
}
When I compile (g++ 4.6.2 20111027), I get the error
problem.h: In member function ‘void aClass::aMemberFunction()’:
problem.h:7:31: error: variable-sized object ‘nums’ may not be initialized
If I comment out the line with int nums[N] I don't get a compilation error, so the similar code for the ints array is fine. Isn't the value of N known at compile time?
What's going on? Why is nums considered a variable-sized array? Why are the arrays nums and ints handled differently?
Isn't the value of N known at compile time?
No. At the time aMemberFunction is compiled, the compiler does not now what N is, since its value is determined at run-time. It is not smart enough to see that there is only one constructor, and assumes that the value of N could be different than 5.
N isn't known at compile time in your example, but it is in this one:
class aClass
{
private:
static const int N = 5;
public:
aClass() {}
void aMemberFunction()
{
int nums[N] = {1,2,3,4,5};
}
};
The above code will compile, and will declare a local array of five ints.
I would like to create a struct and use it inside an other struct as an array. My problem is that I don't know how big array I would like to allocate, I will only know once I am in a function. I mean I would like to use [] instead of a pre-determined constant, like 10000.
I think if you look at my code it would be self-explanatory. Can you help me how to make this code work? Moreover it would help me a lot if you could tell me what is the name of the topic I am asking about (is it dynamic arrays?) and that where can I find articles/tutorials about this topic.
Here is the code with my broken way of thinking about arrays in structs.
#include <iostream>
using namespace std;
struct keyframe {
bool a;
int b;
int c;
};
struct keyframe_file {
const int num_views;
const int num_keyframes;
keyframe keyframes[];
};
int main() {
keyframe_file my_file;
my_file.num_views = 1;
my_file.num_keyframes = 6;
my_file.keyframes = new keyframe[my_file.num_keyframes];
my_file.keyframes[0].a = true;
my_file.keyframes[0].b = 5;
my_file.keyframes[0].c = 9;
return 0;
}
Use a std::vector.
struct keyframe_file {
const int num_views;
const int num_keyframes;
std::vector<keyframe> keyframes;
};
int main() {
keyframe_file frame;
frame.keyframes.resize(...);
}
If it suits your purpose, an STL container (std::vector) is easily one of the best options - the less memory management you have to worry about, the better.
In any case, look at the struct definition Nawaz posted above - that's exactly how it should be. Dynamic arrays in C++ are simply pointers. You have, however, allocated the memory properly in your code, but you haven't freed it (so it's leaking). Since you allocated with new [] you will need to
delete [] my_file.keyframes;
in order to free the memory properly.
Resizing is another issue: with a smart implementation, array resizing can be an amortized O(1) operation which is nice. When you resize, it will always take you O(n) since you need to copy all the elements into a new array of different size, but if you do it half as much, it becomes O(1). That is, double the array each time you need to resize. Here is a very quick example
void resize()
{
if(numOfElementsInArray == sizeOfArray)
{
ArrayType * arr = new ArrayType[sizeOfArray*2]; // Allocate a double size array
for(int i=0;i<sizeOfArray;++i)
currentArray[i] = arr[i];
delete [] currentArray; // Free memory in old array
currentArray = arr; // Set the array to our new one
sizeOfArray *= 2; // Double the size
}
}
NOTE: The example above does not take into account space complexity; that said, if you have 5000 elements, and remove all but 5, this method with not shrink it (which is probably what you will want to do for all practical purposes)
Your code appears to be almost correct, except for two things:
keyframes needs to be a keyframe* rather than a keyframe[]
You forgot to delete the memory you allocated
That is incomplete type. In C++, array must be provided with size, and the size must be known at compile time itself.
You're using new, with which you should be using pointer.
struct keyframe_file {
const int num_views;
const int num_keyframes;
keyframe *keyframes;
};
But std::vector<keyframe> is still a better choice, as #DeadMG already suggested.
By the way, the first two members are const in the struct, that means, they cannot be assigned value, as you're doing in your code. They must be initialized with values you want them to hold. That implies, now with vector, you've to include a constructor, to initialize the struct, as the struct is no more a POD.
struct keyframe_file {
const int num_views; //const member
const int num_keyframes; //const member
std::vector<keyframe> keyframes;
keyframe_file(int nviews, int nkeyframes)
: num_views(nviews), num_keyframes(nkeyframes), keyframes(nkeyframes){}
};
keyframe_file my_file(1,6); //done!
The suggested "Vector" is they safest way to do it.
But if it is only about making your code work (without resizing and stuff) the following should be working:
#include <iostream>
using namespace std;
struct keyframe {
bool a;
int b;
int c;
};
struct keyframe_file {
const int num_views;
const int num_keyframes;
keyframe* keyframes;
};
int main()
{
keyframe_file my_file = {1, 6}; // initialization needed bcause of 'const int'
my_file.keyframes = new keyframe[my_file.num_keyframes];
for (int i = 0; i < my_file.num_keyframes; i++)
{
my_file.keyframes[i].a = true;
my_file.keyframes[i].b = 5 + i;
my_file.keyframes[i].c = 9 - i;
}
return 0;
}
somewhere in your code, when you are done using the array you have to call delete [] my_file.keyframes; as already mentioned.
There's a basic rule when using dynamic arrays in c++, especially when using it inside structs or classes, and it's to delete what you no longer need.
If you want to make your struct dynamic, it's easy, just replace the [] with * and the array will become dynamic, but it's not over yet, there is a lot of work.
You have to construct the array and destory it, and destoroying it is possible and useful noly with destructors, like this:
struct keyframe_file
{
const int num_views;
const int num_keyframes;
keyframe* keyframes;
~keyframe_file() // this is the destructor
{
delete[] keyframes;
}
};
Yet even that code isn't going to work at all, since you are assigning values to constants in variable my_file after creating it, it's illegal in c++, you should then use classes instead.
Using classes with dynamic arrays is very easy and interesting and makes your code very good, you don't have to know too much to do that, just learn what is a constructor, an initializer, destructor, private and public and go on with the following code:
#include <iostream>
using namespace std;
struct keyframe
{
bool a;
int b,c;
};
class keyframe_file
{
public:
keyframe_file(int NV, int NKF):num_keyframes(NKF),num_views(NV)
{
keyframes = new keyframe[num_keyframes];
}
~keyframe_file()
{
delete[] keyframes;
}
private:
const int num_views;
const int num_keyframes;
keyframe* keyframes;
};
int main()
{
keyframe_file my_file(1,6);
return 0;
}
This code works very well, it allows you to assign value to the constants num_views and num_keyframes for one time when creating the object (variable) my_file.
Remember, you are a C++ programmer, be proud of that, and use classes instead of structs and dynamic arrays instead of static ones.
Hope that's useful.
Use pointers and apply to your structure!
int *p;
p = new int;
#include <iostream>
using namespace std;
struct keyframe {
bool a;
int b;
int c;
};
struct keyframe_file {
const int num_views;
const int num_keyframes;
keyframe *keyframes;
};
int main() {
keyframe_file my_file;
my_file.num_views = 1;
my_file.num_keyframes = 6;
for (int i = 0; i < my_file.num_keyframes; i++){
my_file.keyframes = new keyframe; //<---
}
my_file.keyframes[0].a = true;
my_file.keyframes[0].b = 5;
my_file.keyframes[0].c = 9;
return 0;
}