I initialize a dynamic bitset in a constructor of a class and then call a method of that class to fill it with some values. I get a segmentation fault no matter which part of the bitset I try to access.
MyClass::MyClass()
{
boost::dynamic_bitset<> occupancy(200000); // all 0's by default
std::cout << occupancy.size() << "\n";
std::cout << occupancy[1234] << "\n";
fill_occupancy();
}
void MyClass::fill_occupancy()
{
std::cout << occupancy[1234] << "\n";
}
The constructor prints out the correct output of 200000 and 0, but when enters the fill_occupancy methood it gives segfault.
I checked this question, but I don't think that applies, bc I construct the bitset properly as I see the correct output from the constructor.
I've found a way to make it work if I simply make the method fill_occupancy() to accept argument of type dynamic_bitset<> and then call it with fill_occupancy(occupancy). Why this works and the code above does not? Other data types I can call in other methods without having them as argument.
Thank you.
Edit
This is in case someone would be interested in more detailed explanation:
class MyClass()
{
boost::dynamic_bitset<> occupancy; //calls default bitset constructor (i.e size 0)
}
In the MyClass constructor, calling just
MyClass::MyClass()
{
occupancy(200000); // this is WRONG
}
produces error as the occupancy is set to zero size. To resize it one has to call
MyClass::MyClass()
{
occupancy.resize(200000); // this is CORRECT
}
Then occupancy has the correct size and is member of MyClass and as such can be accessed from any other method of the class such as fill_occupancy().
My original construction made the occupancy a local variable of the same name as the member one so in the constructor it worked but everywhere else the member (of size 0) was called which explains the segfault.
Thank again juanchopanza for explanations.
The constructor is instantiating a local bitset called occupancy, not a data member of the same name:
boost::dynamic_bitset<> occupancy(200000); // local variable
It seems like you want to initialize a data member, which you can do like this:
MyClass::MyClass(): occupancy(200000)
{
std::cout << occupancy.size() << "\n";
std::cout << occupancy[1234] << "\n";
fill_occupancy();
}
In your code, "occupancy" is a locale Variable, so you should not access it in the outside.
Related
So, I've been exploring on how to create a dynamical array with a custom template class that I made.
#include <iostream>
#include <vector>
//HOW TO SET CLASS INTO DYNAMICAL ARRAY WITH VECTOR
//CREATE A CLASS
class User{
std::string name;
public:
User(){
}
User(std::string name){
this->name = name;
}
void set_name(std::string name){
this->name = name;
}
std::string get_name(){
return name;
}
};
int main(){
//SET A NORMAL ARRAY THAT CAN CONTAIN AN OBJECT
User user[1];
//DO WHATEVER WITH THE USER[0] TO SET EVERYTHING THAT LATER WILL BE PUT IN VECTOR
user[0].set_name("Meilianto");
std::cout << "user[0]: " << user[0].get_name() << std::endl;
//CREATE A DYNAMICAL ARRAY WHICH IS VECTOR
std::vector<User> vuser;
//PUSHBACK TO THE VECTOR AS "FIRST ELEMENT" BY PUTTING "USER[0]" AS AN ARGUMENT
vuser.push_back(user[0]);
std::cout << "vuser[0]: " << vuser[0].get_name() << std::endl;
//YOU CAN "MODIFIED" THE "USER[0]" AND ADD AGAIN AS THE "SECOND ELEMENT" OF VECTOR
user[0].set_name("Meilianto1");
vuser.push_back(user[0]);
std::cout << "vuser[1]: " << vuser[1].get_name() << std::endl;
//YOU CAN EVEN "MODIFIED" THE "FIRST ELEMENT" BY CALLING THE "METHOD" OF IT
vuser[0].set_name("Hantu");
std::cout << "vuser[0]: " << vuser[0].get_name() << std::endl;
//THE QUESTION HERE, CAN I DECLARE ARRAY TOGETHER WITH THE CONSTRUCTOR?
User user1[1]("Bebek");
//AND AFTER THAT I CAN ADD THAT OBJECT STRAIGHT AWAY TO VECTOR WITHOUT ASSIGNING ALL THE
//MEMBERS ONE BY ONE
return 0;
}
If you have read my comments in my code, what I am trying to do is maybe it will be faster if I just construct right away when I create the object instead of assigning all the members one by one that will cost more code. I imagine if in the future there will be an object with a lot of members and need to assign it one by one. It won't be efficient.
EDIT: I edit the User user[0] into User user[1], Thanks
If you're using a modern standard of C++, then you can do this
std::vector<User> vuser {
{"Meilianto1"},
{"Hantu"},
{"Bebek"}
};
Where each pair of inner brackets with a string calls User constructor, and outer pair of brackets calls std::vector<User> constructor with a sequence of Users
THE QUESTION HERE, CAN I DECLARE ARRAY TOGETHER WITH THE CONSTRUCTOR ?
User user1[1]("Bebek");
You can use list initialization for that, for arrays as well as for vectors:
User users[] { std::string("Herbert"), std::string("Anton") };
std::vector<User> vusers { std::string("Herbert"), std::string("Anton") };
CAN I ADD THAT OBJECT STRAIGHT AWAY TO VECTOR WITHOUT ASSIGNING ALL THE MEMBERS ONE BY ONE
You can initialize a vector with the elements of an previously defined array like this:
std::vector<User> v2users(std::cbegin(users), std::cend(users));
BTW: note that User user[0]; in your code defines an array without elements, i.e. of size 0, which rarely makes sense. Accessing user[0] leads to undefined behaviour
Yes, you can!
User users[]{ User{ "one" }, User{ "two" } };
// Construct vector from iterator-pair:
std::vector<User> users_vector{ std::cbegin(users), std::cend(users) };
You can use emplace_back method or push_back with temporary object to add the vector. For example;
vuser.emplace_back("Meilianto1"); // 1
vuser.push_back(User{"Meilianto1"}); // 2
The first one passes the arguments to the constructor. The second one will move the variable to vector. To be honest, there will be copy elision that's why there will be no move or copy. Just it will construct the variable.
When I have an unsigned int, but I want to find out if it is empty or not, but I need 0, I always declare it as an int and set it to -1. What am I supposed to do, though, when I need the full number spectrum or I am even working with float/double?
With some data-types it is simple, for example std::string which you can just compare to "", but is there a function to check if a variable is empty regardless of data-type, even of custom class objects?
The semantics of a value being missing are exactly why std::optional was introduced to the C++ language specification.
std::optional<unsigned int> value; // by default, the value is missing
if(value) {
// executed if the value is present, it is not
} else {
// this code is executed
}
value = 1;
if(value) {
// This code would now be executed
std::cout << "the value: " << *value << std::endl;
}
This requires a change in thinking regarding the meaning of the variable, but it forces you to think at all times regarding whether or not the variable would be present.
So for example, if you had your own class type MyClass and you wanted to retain a, potentially missing, instance of it, you would do so as follows:
std::optional<MyClass> obj; // Initially missing
obj = MyClass(); // Assigns a newly-created instance of MyClass
obj->foo(); // Calls the 'MyClass::foo' method
obj.reset(); // clears the 'obj' optional
I'm trying to learn C++, and from my understanding if a variable goes out of scope then it is destroyed and its memory is reallocated. If I have a class and it's method creates a variable, shouldn't that variable be destroyed after the method call? For example:
class TestClass {
public:
struct Pair{
std::string name;
int value;
};
void addPair() {
//should be deleted after push_back is called?
Pair x = Pair{ std::string{ "Test Object " }, counter++ };
pairs.push_back(x);
}
void printPairs() {
for (int i = 0; i < pairs.size(); i++) {
std::cout << "pair { " << pairs[i].name << " : " << pairs[i].value << " } " << std::endl;
}
}
void removePair() {
pairs.pop_back();
}
private:
int counter;
std::vector<Pair> pairs;
};
But when I tried addPair() then printPairs() then removePair() it works fine. Why doesn't it throw an error saying invalid access to memory location?
You said:
from my understanding if a variable goes out of scope then it is destroyed and its memory is reallocated.
That is correct. "reallocated" is not correct word I would use. I would phrase that as: The memory used by the object is available to be used by other objects.
And then you asked:
If I have a class and it's method creates a variable, shouldn't that variable be destroyed after the method call?
That is correct.
However, your situation is different.
When you use:
pairs.push_back(x);
a copy of x is placed in pairs. The copy continues to live in pairs after the function returns. Hence, printPairs() and removePair() work just fine.
First, access to variables out of scope is undefined behavior. The program might throw an error but it might even work well. So there's no guarantee an error will be raised.
Second, std::vector::push_back makes a copy of its arguments. So nothing to worry about when passing local variables to it.
Scenario
I am in the process of learning C++, so please forgive my naivety. I have attempted to build my own class, objects and methods - each of which seem to work as expected. However I am running into issues with what seems to be uninitialized storage (and possibly the use of local objects?) however I would like to know how to fix it, if indeed it is meant to be, or an alternative. My current train of thought is that the object needs to be passed...however that could be way off...
Code
//header
class Car{
public:
USHORT GetMin();
void SetMin(USHORT min);
private:
USHORT itsMinPrice;
};
USHORT Car::GetMin(){
return itsMinPrice;
}
void Car::SetMin(USHORT min){
itsMinPrice = min;
}
-
void StartingPrices(){
Car Mercedes;
std::cout << Mercedes.GetMin() << "\n";
Mercedes.SetMin(50);
std::cout << Mercedes.GetMin()<< "\n";
}
int main(){
float input;
Car Mercedes;
Mercedes.SetMin(100);
StartingPrices();
std::cout << Mercedes.GetMin() << "\n";
std::cin >> input;
return 0;
}
Expected output
100, 50, 50
Actual output
debug win32 - 52428, 50, 100
release win32 - 0, 50, 100
In your StartingPrices function, the Mercedes object you call GetMin is created on the line before, i.e., not the same object as the one you create in the main function.
That means that the object do not yet have itsMinPrice set to anything, hence the value will be garbage (that is, a value which you don't really have control over), in this case 52428 in debug and 0 in release.
What I think you wish to do is pass a reference of the Mercedes object from the main function into the StartingPrices function:
void StartingPrices(Car& mercedes){
std::cout << Mercedes.GetMin() << "\n"; // Here the GetMin method will return 100.
...
}
int main(){
....
Car Mercedes;
Mercedes.SetMin(100);
StartingPrices(Mercedes);
....
}
Its also a good idea to set the default value of the members in the constructor of the class.
In your Car class you do not initialize your member variable itsMinPrice except when you call SetMin, this means there is a risk that you will use an uninitialized Car instance if you forget to call SetMin on it. Normally it is good to have initialization in a constructor of the class with some value e.g.
Car() : itsMinPrice(0) {
}
or create a constructor that takes an initial value
Car(USHORT minValue) : itsMinPrice(minValue) {
}
I have a simple function that I simplified to return just a dummy list (to ensure its not some logic error)
vector<AttrValue>* QueryEvaluator::getCandidateList(...) {
...
values.clear();
values.push_back(2);
values.push_back(3);
cout << "values is of size " << values.size() << endl;
return &values;
}
then in a cppunit test:
vector<AttrValue>* candidateList0 = evaluator->getCandidateList(cl, 0);
cout << candidateList0->size() << endl;
But problem is size(), in the test, is always 0 even though the cout message prints the correct size 2. What might be wrong?
I tried a simple program and it appears to be fine ...
#include <iostream>
#include <vector>
using namespace std;
vector<int>* test() {
vector<int> vec { 2, 3, 6, 1, 2, 3 };
return &vec;
}
int main() {
cout << test()->size() << endl;
return 0;
}
You are returning a the address of temporary from getCandidateList function, the object is release when function returns. access to it is undefined behavior. You could just return the vector out, RVO should come to apply and elide the copy:
Try:
std::vector<AttrValue> QueryEvaluator::getCandidateList(...)
{
//blah
return values;
}
I tried a simple program and it appears to be fine ...
the temporary vector is released when getCandidateList function returns. The program has undefined behavior.
Your vector appears to be declared on the stack so will be destroyed when it goes out of scope (when the function exits). If you want to return a pointer to a vector, allocate it on the heap instead
vector<AttrValue>* QueryEvaluator::getCandidateList(...) {
vector<AttrValue>* values = new vector<AttrValue>();
...
values->clear();
values->push_back(2);
values->push_back(3);
cout << "values is of size " << values->size() << endl;
return values;
}
It might be easier to instead declare it in the caller and pass a reference to getCandidateList
void QueryEvaluator::getCandidateList(vector<AttrValue>& values)
...or return it by value
vector<AttrValue> QueryEvaluator::getCandidateList(...) {
So many interesting things to consider:
vector<AttrValue>* QueryEvaluator::getCandidateList(...) {
...
values.clear();
values.push_back(2);
values.push_back(3);
cout << "values is of size " << values.size() << endl;
return &values;
}
So it looks like you left out the most interesting piece in the code ... above. Moral of the story try and provide compilable working code that shows the error. Reducing your problem to a small example usually results in you finding the problem yourself. At the very least you should provide exact definitions of all objects that are used (the type is the most important thing in C++)
Does it declare the vector as a local object?
std::vector<int> values;
In this case the vectors lifespan is bound to the function and it is destroyed at the end of the function. This means using it after the function has returned is undefined behavior (anything can happen).
But it also looks like you are using objects as part of you unit test framework. So a potential solution is to make the vector part of the object. Then the vector will live as long as the object (not just the function call) and thus returning a pointer to it will work as expected.
class QueryEvaluator
{
std::vector<int> values;
public:
vector<AttrValue>* QueryEvaluator::getCandidateList(...);
};
An alternative would be to return the vector by value rather than a pointer. This means the object will be correctly copied out of the function and your calling code can manipulate and test the vector all they need.
vector<AttrValue> QueryEvaluator::getCandidateList(...)
{
...
return &values;
}
Side Note:
Also you need to try not to use pointers in your code. Pointers doe not convey any ownership.This means we do not know who is responsible for deleting the object. In this case a reference would probably have been better (you never return NULL) as this gives the caller access to the object will retaining ownership (assuming you decided not to return by value).