c++ std::set insert causing segmentation fault - c++

All-
I can't quite figure out why this piece of code is resulting in a segmentation fault... Any help would be great.
#include <iostream>
#include <set>
using namespace std;
class A{
public:
int _x;
A(int x){
_x = x;
}
};
bool fncomp(A a1, A a2){
return a1._x < a2._x;
}
int main(){
bool(*fn_pt)(A,A) = fncomp;
set<A, bool(*)(A,A)> testSet;
for(int i=0; i<10; i++){
cout << i << endl;
A a(i);
testSet.insert(a);
}
}
The output is:
0
1
Segmentation Fault

Well, look at your code. You declared a function fncomp, but are you really using that function anywhere? You initialize fn_pt with it, but fn_pt is not used anywhere. Doesn't it seem strange to you? How do you expect your testSet object to know that you want it to use your fncomp as the comparator, if you never ask your set object to use that function?
You declared your set testSet with an ordinary function pointer type bool(*)(A,A) as a comparator type. That's the type of the comparator. Now, you have to pass the actual value of the comparator to your set object through the constructor parameter
set<A, bool(*)(A,A)> testSet(fn_pt);
or
set<A, bool(*)(A,A)> testSet(fncomp);
(You don't really need that intermediate pointer fn_pt).
You forgot to do that, and the set object used the default constructor argument value for the comparator, which in this case is a null pointer. So, every time your testSet object tries to compare two elements, it performs a function call through a null pointer. No wonder it crashes.

Didn't you get a compiler warning about the unused variable fn_pt?
The variable testSet has an internal comparator of the specified type bool(*)(A,A). Since you didn't initialize it, it was default initialized as NULL. So when testSet tried to insert A(1), it tried to invoke a null function pointer to figure out which order is correct.
You probably meant:
set<A, bool(*)(A,A)> testSet(fn_pt);

Related

How would I initialise a 2D vector of objects in a constructor of a class? (C++)

I am currently attempting to create a class containing a 2D vector of structs, however I am clearly doing something tragically wrong as whenever I run my code, I get the error at line 19 (the line in the for loop in the world constructor) error: expected primary-expression before ‘)’ token
Here is my code at the moment:
#include <iostream>
#include <vector>
struct Cell{
bool isAlive;
Cell(bool alive){
isAlive = alive;
}
};
class World{
unsigned width;
unsigned height;
std::vector<std::vector<Cell>> state;
public:
World(unsigned w,unsigned h){
width = w;
height = h;
for (int i = 0; i<h; i++){
state.push_back(std::vector<Cell>);
}
}
};
I know that I haven't yet fully initialised the 2nd dimension of the vector, but I'm just trying to get this working at the moment.
Thank you so much, I honestly have no clue what this error means.
You need to construct the vectors you are attempting to push_back.
// Note the added parentheses after <Cell>
state.push_back(std::vector<Cell>())
In this case, push_back is expecting a value, or an "expression" which evaluates to a value. Your expected primary expression before ')' token error more or less means that push_back was expecting a value as its parameter but was passed something else. In this case, that something else was the type std::vector<Cell>. Constructing the vector (creating a value with an expression) will fix the issue.
Ever heard of "there is no spoon"? In this case, there is no vector. You cannot pass a type, you have to pass an instance or value in this case.

How to use void* as a single variable holder? (Ex. void* raw=SomeClass() )

I am trying to make void* to hold a value (to avoid default constructor calling).
I want to:-
copy K to void* e.g. K k1; --> void* raw=k1;
copy void* to K e.g. void* raw; --> K k2=raw;
try not to break destructor and causes memory leak
don't use any dynamic allocation (heap, performance reason)
Here is what I tried:-
class K{
public: std::string yes="yes" ;
};
int main() {
//objective: k1->raw->k2 , then delete "raw"
void* raw[sizeof(K)]; //<--- try to avoid heap allocation
K k1;
static_cast<K>( raw)=k1; //<--- compile fail
K k2= static_cast<K>( raw);
std::cout<<k2.yes; //test
static_cast<K&>(raw)::~K(); //mimic destructor
return 0;
}
Question: Please provide a valid code that demonstrate a correct way to do this.
I found how to use placement new (https://stackoverflow.com/a/4756306/3577745 ), but not found how to use void* for a variable that is not an array.
C++ is new for me.
Edit :
I am writing a very custom collection (array).
Each element is encapsulated in a custom structure KCap kcap(with hold only 1 element, i.e. K).
Thus, I have to declare K k as a field of the encapsulator KCap.
However, I want to avoid default constructor of K, so I think void* can solve my issue.
What you are trying to do doesn't make sense. A void * is used to hold an arbitrary type of pointer, not an arbitrary type of other object. If you want to use storage for an arbitrary object type, use a char[].
Other problems with your code include that you need to ensure correct alignment of the raw storage, use reinterpret_cast to a reference rather than static_cast to a non-reference, your in-place destructor call syntax is wrong, and that you don't construct the K object in the "raw" storage. Here's a corrected version:
#include <string>
#include <iostream>
class K{
public: std::string yes="yes" ;
};
int main() {
//objective: k1->raw->k2 , then delete "raw"
alignas(alignof(K)) char raw[sizeof(K)]; //<--- try to avoid heap allocation
K k1;
new (reinterpret_cast<K *>(&raw)) K(k1); //<--- compile now succeeds :)
K k2= reinterpret_cast<K &>(raw);
std::cout << k2.yes << std::endl; //test
reinterpret_cast<K&>(raw).K::~K(); // call destructor
return 0;
}

Initialize a C++ vector with a variable inital value

I was coding up a Union find data structure , and was trying to initialize the parent vector with a value parent[i]=i, Is there a way in c++ to initialize the vector like this , that is declaring a vector of size N , and not assigning fixed values to each element, rather position dependent value to each element. (without using any obvious for loops)
This is what I was looking for:
std::vector<int> parent(Initializer);
where Initializer is some class or a function.
To try out my hand a bit, I wrote this:
#include <iostream>
#include <vector>
using namespace std;
class Initializer {
private:
static int i;
public:
int operator() ()
{
return i++;
}
};
int main()
{
vector<int> parent(Initializer);
cout << parent[0];
return 0;
}
However I think I have messed up my concepts pretty bad here, and I am not getting what the declaration means, or what it is doing.
Please answer both the questions,
(1) How to initialize a vector with variable initial values.
(2) What exactly is the code I wrote doing?
This is a function declaration:
vector<int> parent(Initializer);
Becasue Initializer is a type name, you declared a function parent that takes Initializer as a (unnamed) parameter and returns vector<int>. See Most vexing parse.
To do what you want, you can do this:
std::vector<int> parent(N); // where N is the size you want
std::iota(parent.begin(), parent.end(), 0); // fill it with consecutive values
// starting with 0
There's std::generate algorithm that you can use to save result of a function (or function object) in a range:
std::generate(parent.begin(), parent.end(), Initializer());
Live demo.
There are several alternatives. If you want to initialize the vector with increasing values, then you can use std::iota.
std::vector<int> vec(size);
std::iota(std::begin(vec), std::end(vec), 0);
If you want something more general you could use std::generate.
std::vector<int> vec(size);
int n = 0;
std::generate(std::begin(vec), std::end(vec), [&n]() {return n++;});

Passing vector to a function gives error. c++

This is a noob question, sorry but, I just started using vectors in c++. Here's is the code I am struggling with.
int main()
{
//some code
int n;
cin>>n;
vector <int> a(n+1,0);
int first=find(&a,d); //d has some value from the upper portion of the code
}
int find(vector <int>* a,int o)
{
int b=o;
while(a->b!=0)
b=a->b;
return b;
}
Q1 : Why doesn't passing vector like find(a,d) work like it does in arrays.?
Q2 : In the find function, Why do I have to access the vector elements with "." or "->". Shouldn't a[b] work? If that is the correct way then why does a[b] work in the main function?
Q3 : What's wrong with the code? When I compile I get the error
In function ‘int find(std::vector<int>*, int)’:
error: ‘class std::vector<int>’ has no member named ‘b’
I understand the error, but then how do I access the required element?
Thanks in advance. :)
Why doesn't passing vector like find(a,d) work like it does in arrays.?
Arrays are passed by "decaying" into a pointer to the first element; so they are effectively passed by reference.
Vectors are straightforward object types, passed by value unless the function is declared to take a reference. A function taking it by value will get a separate copy of it.
You could change the function to take the vector by reference:
void find(const std::vector<int> & a, int o);
^
The const is optional, but is a very good idea if the function doesn't need to modify the vector.
In the find function, Why do I have to access the vector elements with "." or "->".
You don't. You access class members of the vector itself (such as size()) like that.
Shouldn't a[b] work?
It would if a were an object or reference. Since it's a pointer, you have to dereference it, (*a)[b]
If that is the correct way then why does a[b] work in the main function?
In the main function, 'a' is an object, so can be used directly as an operand.
You should study vectors, templates, the c++ way to do that.
Take a look at: http://www.cplusplus.com/reference/vector/vector/
Q1 : Why doesn't passing vector like find(a,d) work like it does in arrays.?
Because it is not an array, its an object, so you can pass it as copy and not referece, you just pass it as a reference if you change the value.
Q2 : In the find function, Why do I have to access the vector elements with "." or "->". Shouldn't a[b] work? If that is the correct way then why does a[b] work in the main function?
a[position] returns the element
a->b dont work, you cannot access the b as an element
Use a->at(position) to access every element in the vector
Example (you can use iterators too)
for(int x=0; x<a->size();x++)
cout << a->at(x);
Q3 : What's wrong with the code? When I compile I get the error
The previous question answers that.
You dont have the b element, the A is a vector it contains elements.
If you want to get the element at the position B do a->at(b).
If you want to find use
for(int x=0; x<a->size();x++)
if(a->at(x) == b) return x; //returns the position
You're saying:
int b = o;
while(a->b!=0)
b=a->b;
return b;
when you mean:
for(vector<int>::const_interator i = a.begin(); i != a.end(); ++i)
if (*a == o)
return a.end() - i;
return a.size();

How can I initialize an array globally in C or C++?

I'm trying to do this:
for(int k=0; k<context.size(); k++)
{
cc_no_issue[k]=0;
}
Can someone tell me how I can do that globally? Whenever I try I get these errors:
expected unqualified-id before "for"
k does not define a type
k does not define a type
This will do:
long cc_no_issue[100]={0};
And this is the proper initialization.
Note: this will initialize all the contents to 0.
This sentence:
long cc_no_issue[100]={1,2};
will set cc_no_issue[0] to 1, cc_no_issue[1] to 2, and the rest to 0. You could see the link above for more information.
If you have a global array of a basic type,
int some_array[1000];
It will automatically be initialized to zero. You do not have to initialize it. If you do need to run initialization code, you can do a hack like the following (in C++):
struct my_array_initializer {
my_array_initializer() {
// Initialize the global array here
}
};
my_array_initializer dummy_variable;
If you are on GCC (or Clang), you can execute code before main with the constructor attribute:
__attribute__((constructor))
void initialize_array()
{
// Initialize the global array here
}
All global variables (variables at file scope) are by default initialized to zero since they have static storage duration (C99 6.7.8.10). So strictly speaking, you needn't initialize them to zero, the C standard guarantees that they are zero by default.
It is good programming practice to initialize them explicitly however, as mentioned in the answer by Ziyao Wei.
No, you can't have code outside of functions.
You can put it inside some function and call that from the start of main.
One way is to add a global function that:
Checks if the array is initialized
Initializes the array if it wasn't initialized
Returns the array
Example Code:
int* get_cc_no_issue()
{
if(!kIsMyArrayInitialized)
{
/* todo: somehow get "context" globally... */
for(int k = 0; k < context.size(); k++)
{
cc_no_issue[k] = 0;
}
kIsMyArrayInitialized = true;
}
return cc_no_issue;
}
This is most useful if you want non-zero initialization.
For zero-initialization, see this answer to another question:
Is global memory initialized in C++?
You can put the array in the constructor of a global object.
int cc_no_issue[256];
struct Init {
Init(int a, unsigned int size)
{
memset(a, 0, size);
}
};
Init arr(cc_no_issue, sizeof(cc_no_issue));
As #Bo Persson, do it in a function instead. But, there is already an algorithm that does it for you in C++. No need to write a hand written loop.
std::fill(cc_no_issue, cc_no_issue+context.size(); 0) ;
More info on std::fill
Response to your comment:
To increment every element, you can make use of std::for_each passing a function object as the third argument.
#include <iostream>
#include <algorithm>
using namespace std;
void incrementHelper( int& a ){
++a;
}
int main(){
int ar[] = { 1,2,3,4,5 };
for_each(ar, ar+5, incrementHelper );
for( int i=0; i<sizeof(ar)/sizeof(ar[0]); ++i ){
cout << ar[i] << endl;
}
return 0;
}
Ouput:
2
3
4
5
6
for_each(ar, ar+5, incrementHelper );
For each element in the array, the algorithm is going to call the function, incrementHelper. In C terminology,to say, it serves as a call back for each element in the array. Now the call back function, receives the passed element by reference. So, modifying the reference will modify the referrent also. See the online demo.
You need to decide on the language. The machanisms for this are different in C and C++. Basically C has no method of running code before your main function starts, so you cannot do complex initialisation of an array in C. In C++ you do have some options, one is to stop using a bare array (which is a C construct anyway) and instead wrap your array inside a class, and do the initialisation inside the class constructor.
CC cc_no_issue;
class CC
{
public:
CC()
{
// initialisation of array goes here
}
private:
int array[100];
};
Another way it to use a vector, and write a function to initialise the vector.
std::vector<int> cc_no_issue = init_vector();
std::vector<int> init_vector()
{
std::vector<int> tmp;
// initialisation of tmp goes here
return tmp;
}