c++ strange syntax - c++

i dont understand some things in a code from a tutorial
first one: what is that comma "," doing in the middle there? is it mb a overloaded operator?
u32 TimeStamp = irrTimer->getTime(), DeltaTime = 0;
next i have a weird constructor from class CharacterDemo, why is there a ":" following some variables with weird brackets? im guesseing they are beeing initialized with the value in the brackets.. ?
CharacterDemo::CharacterDemo()
:
m_indexVertexArrays(0),
m_vertices(0),
m_cameraHeight(4.f),
m_minCameraDistance(3.f),
m_maxCameraDistance(10.f)
{
m_character = 0;
m_cameraPosition = btVector3(30,30,30);
}
im rly curiouse, explanation much appriciated

It's an initialization list.
It calls the constructors of the members and parent classes of the specified class.
Note that you can only use it in the constructor of a class (because it only happens at its construction).
[edit] For your first question, it's a way to declare multiple variables of the same type at once. Note that it will not always work as expected : int * a, b will declare a variable a of type int *, and another variable b of type int (not a pointer).

what is that comma "," doing in the middle there?
A statement like int i = 3, j = 4; is the same as int i = 3; int j = 4;
So, u32 TimeStamp = irrTimer->getTime(), DeltaTime = 0; is defining and initializing two variables of type u32: one named TimeStamp and the other named DeltaTime.
why is there a ":" following some variables with weird brackets? im guesseing they are being initialized with the value in the brackets.. ?
That's correct: google for c++ member initialization list.

Related

variable declaration in function return type specifier c++type

I was trying out codefights.com and noticed someones answer to a question which involved giving all the longest strings in a vector do this:
std::vector<std::string> r, allLongestStrings(std::vector<std::string> a) {
int b=0;
for (s:a) if (s.size()>b) b=s.size();
for (s:a) if (s.size()==b) r.push_back(s);
return r;
}
He's declaring a variable in the return type specifier for the function, can anyone tell me why this is allowed? I't doesn't compile on my machine and I couldn't find a gcc extension that does this, thanks in advance :).
Looking at the reference (decl-specifier-seq), I don't see how it would be possible to declare the return variable before the function name.
With C++14, you can use the auto keyword to remove the duplicate mentioning of the return type:
auto allLongestStrings( const std::vector<std::string>& a ) {
std::vector<std::string> r;
std::size_t b = 0;
for( const auto& s : a ) if( s.size() > b ) b = s.size();
for( const auto& s : a ) if( s.size() == b ) r.push_back( s );
return r;
}
I fixed some other things of the code:
to improve efficiency, declare the parameter a as const reference, so it won't be copied
declare b as std::size_t to match return type of std::vector::size()
in range-for loop, a type specifier is necessary (even if it is auto); added const reference for efficiency
Live demo.
The mixed variable / function declaration seems to be ok, though gcc complains that function definition shouldn't be there but I think it's ok at global scope. But it's a 100% valid syntax even in non-global scope if no function definition is given. This declaration is just regular declarations of several items of the same leading type. For example we can declare multiple items of different kinds but with same leading like this:
// single line declaration
int i = 0, * p_i = nullptr, ai[2] = {42,42}, geti(void), * * getppi(void);
// the same as
int i = 0;
int * p_i = nullptr;
int ai[2] = {42, 42};
int geti(void);
int ** getppi(void);
So r is just a regular variable of type std::vector<std::string>, followed by function allLongestStrings that returns the same std::vector type.
This compact declaration form exists for historical reasons. Basically it helped to save quite some bytes for storing and compiling the source file.
This form of for loop is probably on of the earlier experimental extensions before current form was standardized.

Multiple variable declare and initialization inside for-scope [duplicate]

This question already has answers here:
Can I declare variables of different types in the initialization of a for loop? [duplicate]
(5 answers)
Closed 9 years ago.
I'm trying to declare and initialize variables of different type inside a for-scope.
Something like:
for (int i = 0, double u = 1; i < 10; ++i)
{...}
but the compiler (gcc) returns me an error.
I know that can perform initialization using the same type variables (example), but I don't know how is it possible do it with different ones.
Of course I can declare the variable outside the loop:
double u = 1;
for (int i = 0; i < 10; ++i)
{...}
but I'm looking for something clean because the variable u is used only inside the for-scope.
So,
Can I do it?
If so, how can I?
Its not allowed to declare more then one type in a declration statement. The only way to contain u within the scope remotely close to the for loop would be something like that:
{
double u = 1;
for (int i = 0; i < 10; ++i)
{
//some code
}
}// u's scope will end here
Of course creating a new scope will do, but writing a function is more common way.
void foo()
{
// So this function deals with loop and does something with 'u'.
double u = 1;
for (int i = 0; i < 10; ++i)
{ ... }
}
It is hard to say if you really need a function, but I believe it is a very clean and natural way.
You have to think as if you are declaring these variables in another part of the code.
You can declare as many variables as you want in the same line always if they share the type.
You can declare:
int a=3, b=3;
But the ';' points the end of this type declaration. If you try to do:
int a=3, double b= 3.4;
As you wish the compiler translate that as a "double" declaration of the b variable. First the compiler recognize it as an int, but then you are specifying another type. Thats why you can't do that. If you try to do it as your compiler wish (type variable=value; another_type another_variable = another_value;) you'll break the for structure.

Getting 'Non-constant expression as array bound' when field is const

I'm trying to define a multidimensional array using my constant field as its dimension, but I'm getting a compilation error saying that the expression is not constant. Is there any other way to do this so I can use a constant field defined in constructor initialization list as an array dimension?
Translation for English-speaking majority:
class FunctionWave2D : public DisallowedDomainPoints
{
protected:
double th;
double l; a
double d, dd;
const int number_sqrt; //here's the constant
double **second_derivatives;
protected:
bool elasticTenstionOnly;
public:
FunctionWave2D(int number, double elasticModulus, double dampingFactor, double oscillationDampingFactor, double length)
:DisallowedDomainPoints(number * LAYER_COUNT),
th(elasticModulus), d(dampingFactor), dd(oscillationDampingFactor),
elasticTensionOnly(false),
l(length/(sqrt(number)-1)),
number_sqrt(sqrt(number))
{
second_derivatives = new double[number_sqrt][number_sqrt][LAYER_COUNT];
//(...)
In C++, the term "constant expression" specifically refers to an expression whose value is known at compile-time. It's not the same as a const variable. For example, 137 is a constant expression, but in this code:
int function(int x) {
const int k = x;
}
The value of k is not a constant expression, since its value can't be determined at compile-time.
In your case, you have a data member declared as
const int ilosc_sqrt; //here's the constant
Even though this is marked const, its value is not known at compile-time. It is initialized in the initializer list as
ilosc_sqrt(sqrt(ilosc))
This value can't be determined until the program is actually run, hence the error. (Note that the new C++11 constexpr keyword is designed, among other things, to make constant expressions a lot easier to identify in source code and to make it possible to do more advance compile-time computations with constants.)
To fix this, you will either need to split up your initialization into smaller steps:
drugie_pochodne = new double**[ilosc_sqrt];
for (int i = 0; i < ilosc_sqrt; i++) {
drugie_pochodne[i] = new double*[ilosc_sqrt];
for (int j = 0; j < ilosc_sqrt; j++) {
drugie_pochodne[j] = new double[ILOSC_WARSTW];
}
}
Or use a library like Boost.MultiArray, which supports a cleaner initialization syntax.
Hope this helps!
An array bound has to be a compile-time constant. A non-static const data member is not a compile-time constant; it gets its value at runtime, when the object is constructed.
So, basically, if you need to set the size of that array at runtime you'll have to build up all the pieces with operator new[]. Essentially,
int **data_2d = new int*[runtime_size];
for (int i = 0; i < runtime_size; ++i)
data_2d[i] = new int[runtime_size];
The extension to a 3d-array is straightforward.

Strange multiple assignment error in C++

I have multiple assignment statement in my program as shown below where query.constraints.size() is supposed to return 13 (constraints is an array and its returning its size)
int num,size = query.constraints.size();
When I do this size becomes 13 as expected but num becomes 9790272 for some reason.
When I do them separately as below everything is ok and both of them are 13 as expected
int size = query.constraints.size();
int num = query.constraints.size();
Why does my multiple assignment result in a strange a strange value ?
Why does my multiple assignment result in a strange a strange value ?
Because C++ has no multiple assignment1. You are declaring two variables here, but only initialise the second, not the first.
1 Well, you can do int a, b = a = c; but code which does this would be deemed bad by most C++ programmers except in very peculiar circumstances.
You're not assigning multiple times, you're declaring multiple times. You need to do something like:
int num, size;
size = num = query.constraints.size();
A mutiple assignement would looks like:
int num, size;
num = size = query.constraints.size();
But the comma operator does not do a multiple assignement.
What you have is actually a declaration statement, partially with initializer. Your code is equivalent to this code:
int num; // uninitialized, you're not allowed to read it
int size(query.constraints.size()); // initialized
In general, T x = expr; declares a variable x of type T and copy-initializes it with the value of expr. For fundamental types this just does what you expect. For class-types, the copy-constructor is only formally required, but in practice usually elided.
The comma operator doesnt do what you think it does

Using the comma operator in if statements

I tried the following:
if(int i=6+4==10)
cout << "works!" << i;
if(int i=6+4,i==10)
cout << "doesn't even compile" << i;
The first works fine while the second doesn't compile. Why is this?
EDIT: Now I know that the first one may not work as I intend it to. The value of i inside the if scope will be 1, not 10. (as pointed out by one of the comments on this question).
So is there a way to initialize and use a variable inside of an if statement at the same time similar to for(int i=0;i<10;i++)? So that you could produce something like if((int i=6+4)==10) (which will not compile) where the value of I inside the if scope would be 10?
I know you could declare and initialize I before the if statement but is there a way to do this within the statement itself?
To give you an idea why I think this would be usefull.
if(int v1=someObject1.getValue(), int v2=someObject2.getValue(), v1!=v2)
{
//v1 and v2 are visible in this scope
//and can be used for further calculation without the need to call
//someObject1.getValue() und someObject2.getValue() again.
}
//if v1==v2 there is nothing to be done which is why v1 und v2
//only need to be visible in the scope of the if.
The expression used as an initializer expression must be an assignment-expression so if you want to use a comma operator you must parenthesize the initializer.
E.g. (not that what you are attempting makes much sense as 6 + 4 has no side effects and the value is discarded and i == 10 uses the uninitialized value of i in its own initializer.)
if (int i = (6 + 4, i == 10)) // behaviour is undefined
Did you really mean something like this?
int i = 6 + 4;
if (i == 10)
When using the form of if that declares a new variable the condition checked is always the value of the initialized variable converted to bool. If you want the condition to be an expression involving the new variable you must declare the variable before the if statement and use the expression that you want to test as the condition.
E.g.
int i;
if ((i = 6 + 4) == 10)
I doubt seriously either example works to do anything useful. All that it does is evaluate to "true" in a complicated fashions.
But the reason the second one doesn't compile is that it's interpreted as two declarations: int i = 6+4; int i==10 and int i==10 isn't valid because that's an equality operator, not an assignment.
There are different alternatives, because what you want cannot be done (you cannot mix the comma operator with declarations). You could, for example, declare the variable outside of the if condition:
int i = 6+4;
if ( i == 10 ) ...
Or you can change the value of i to be 0 instead of 10 and recalculate i inside the else block:
if ( int i = (6+4)-10 ) ; else {
i += 10;
// ...
}
Much simpler, don't declare the variable at all, since you know the value inside the loop:
if ( (6+4)==10 ) {
int i = 10;
// ...
}
Unless of course you need the value of i in the case where it is not 10, in which case the second option is the most appropriate.
As of C++17 what you were trying to do is finally possible:
if (int i=6+4; i==10)
cout << "works, and i is " << i << endl;
Note the use of ; of instead of , to separate the declaration and the actual condition.