I see some people tend to initialize a vector with an empty {}, and I wonder whether it is different from directly initialize with the default constructor?
for example:
#include <vector>
#include <iostream>
using namespace std;
int main()
{
vector<int> vec;
vector<int> vec2 {};
cout << sizeof(vec) << " " << sizeof(vec2) << endl; // 24 24
cout << vec.size() << " " << vec2.size() << endl; // 0 0
}
and I check its assembly code, and it shows that initializing a vector with an empty {} generate more code(https://godbolt.org/z/2BAWU_).
Assembly code screen shot here
I am quite new to C++ language, and I would be grateful if someone could help me out.
Using braces is value initialization. Not using them is default initialization. As somebody alluded to in the comments, they should generate the exact same code when optimizations are turned on for vector. There's a notable difference with built-in types like pointers and int; there default initialization does nothing, while value initialization sets them to nullptr and zero, respectively.
Related
Consider, for example:
#include <array>
#include <iostream>
int main()
{
using Ram_bank = std::array<char, 0x2000>;
std::cout << "Size of ram bank is: " << Ram_bank::size() << '\n';
return 0;
}
Obviously this is not valid code, as Ram_bank is not an actual type or object but an alias. But, is there some way to achieve this? Is there a way to get the size of an aliased type?
Your code is not failing because Ram_bank is an alias. It is failing because size() is non-static and you would need an instance to call it on. Kosta's answer is an example of that.
Alternatively, you can use std::tuple_size:
std::cout << "Size of ram bank is: " << std::tuple_size<Ram_bank>::value << '\n';
You could instantiate an array and then take it's size (since std::array::size is a non-static member function). Every half-decent compiler should optimize this away:
std::cout << "Size of ram bank is: " << Ram_bank().size() << '\n';
My program can not show Fibonacci series but I think the code is right does anyone know why?
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <math.h>
using namespace std;
int main()
{
int a=0,b=1,c;
cout << "Fibonacci number" << endl;
cout << a << " ";
cout << b << " ";
while (c<100)
{
c=a+b;
a=b;
b=c;
}
cout << c << " ";
return 0;
}
There are two errors in your code, as already stated in the comments by someone else.
First, you are trying to use c without initializing it. Remember that in C++, when declaring a built-in type without initializing it, it is 'default initialized'. In other words, if you declare a variable of built-in type inside a function (in this case the main() function), it's value is undefined. Thus, you can't use it to check for a condition before assigning a value to it, and this is precisely what your while loop does.
Second, you are only pushing into the ostream the last calculated value of c. In other words, you are only printing the last value of you Fibonacci sequency.
Try putting your cout << c statement inside your loop.
PS.: Use the C++ version of C libraries whenever possible (i.e. <cstdio> instead of <stdio.h>, etc)
Consider the following snippet:
#include <iostream>
using namespace std;
int a[10][2];
int b[10][2];
int main(){
//intended
cout << a[0][0] - b[0][0] << endl;
//left out dimension by mistake
cout << a[0] - b[0] << endl;
}
Obviously (or maybe not per comments) the second case is valid pointer arithmetic in both C and C++ but in the code base I am working with it is generally a semantic mistake; a dimension has usually been left out in a nested for loop. Is there any -W flag or static analysis tool that can detect this?
You could use std::array which will not allow that:
using d1=std::array<int, 2>;
using d2=std::array<d1, 10>;
d2 a;
d2 b;
std::cout << a[0][0] - b[0][0] << endl; // works as expected
std::cout << a[0] - b[0] << endl; // will not compile
Another option is to use a specialized multidimensional array library with appropriate operator error handling, such as boost::multi_array (http://www.boost.org/doc/libs/1_55_0/libs/multi_array/doc/user.html). This is usually a better idea then using nested containers or POD arrays.
If this is only concern for << operator as in example, overload of operator << for int* might help - you can overload operator to generate compile-time error.
I'm wondering on how to properly loop over the members of a plain old data type, in order to get some type information on them. That is :
struct my_pod
{
int a;
double b;
};
template<typename POD>
void loopOverPOD()
{
for_each(POD, member) // The magic part
{
// member::type should be for my_pod int, then double
typename member::type i;
// member::size_of should be equal to sizeof(int) then sizeof(double)
// Trivial if we can have member::type information.
int size = member::size_of;
// member::offset_of should be equal to 0, then sizeof(int)
// Trivial if we can have member::size_of information.
int offset = member::offset_of;
}
}
As far as I know in C++, we can't do easy type introspection without doing some tricky plays with templates. But here, I can't find a concrete solution with templates, even with the use of macro in fact. And the problem is more about me rather than about the existence of a solution. :-)
I'm not necessarily asking for a solution that would not be intrusive.
Thanks in advance.
You could use boost.fusions ADAPT_STRUCT to turn your POD into a sequence and then use fusions for_each to apply a function object to each member. This is non-intrusive, your POD type will remain POD.
The good thing is that you could even put the ADAPT_STRUCT macros in a (header-) file separate from your struct definitions and only use them in code where you need to iterate.
The flip side is that this macro requires the redundancy of mentioning both the type and the name of the members again. I imagine that at some point fusion will use C++11 features to get rid of that redundancy (mentioning the type again). In the mean time, it is possible to create a macro that will declare the struct and the ADAP_STRUCT part.
If you use C++14 and newer, you can use Boost.Precise and Flat Reflection (https://github.com/apolukhin/magic_get/) for looping over your POD and boost::typeindex::type_id_runtime(field) to print type:
#include <iostream>
#include <boost/pfr/precise.hpp>
#include <boost/pfr/flat.hpp>
#include <boost/type_index.hpp>
struct my_pod
{
int a;
double b;
};
struct my_struct
{
char c;
my_pod pod;
};
int main() {
my_pod val{1, 2.5};
my_struct var{'a', 1, 2.5};
std::cout << "Flat:\n";
boost::pfr::flat_for_each_field(var, [](const auto& field, std::size_t idx) {
std::cout << idx << ": " << boost::typeindex::type_id_runtime(field) << "; value: " << field << '\n';
});
std::cout << "\nNot Flat:\n";
boost::pfr::for_each_field(var, [](const auto& field, std::size_t idx) {
using namespace boost::pfr::ops;
std::cout << idx << ": " << boost::typeindex::type_id_runtime(field) << "; value: " << field << '\n';
});
}
Output for this example:
Flat:
0: char; value: a
1: int; value: 1
2: double; value: 2.5
Not Flat:
0: char; value: a
1: my_pod; value: {1, 2.5}
Though I'm not sure how to get offset in this case...
C++ has no construct to iterate through members of a structure.
There exists however a standard type std::tuple for which you can use templates to recursively iterate through its elements at compile time.
Could someone explain to me why the offsetof function does not work on std::vectors as shown below:
#include <windows.h>
#include <iostream>
#include <vector>
using namespace std;
struct FooStruct {
double x;
double y[10];
std::vector<double> z;
};
int main() {
cout << offsetof(FooStruct, x) << endl;
cout << offsetof(FooStruct, y[2]) << endl;
cout << offsetof(FooStruct, z[2]) << endl;
system("Pause");
}
Calling offsetof(FooStruct, z[2]) produces the following compiling error:
cannot apply 'offsetof' when 'operator[]' is overloaded
offsetof(FooStruct, z[2]) makes no sense. The elements of z are not contained within a FooStruct, they're accessed via the std::vector, which has at its core a pointer to some other allocation on the heap within which z[2] can be found.
In any case, the error (which seems confusing I understand) is probably popping up because std::vector overloads operator[], not because your class FooStruct overloads operator[] (which, assuming we see the whole definition, it doesn't).
If you want to find the offset of z[2] in relation to z[0], you could just compute the difference between &z[0] and &z[2] like this: std::cout << (&z[2] - &z[0]) << '\n';
Because offsetof isn't a function but a macro, and only works on POD types, or standard layout class in C++11. It's only there for backward compatibility with C.
The reason the compiler refuses to allow you to use the subscription operator, all issues aside, is because the macro is evaluated at compile time, but the overloaded operator might do some work at runtime to calculate the result.