This is the simplest I could work my problem down to, sorry about the length:
#include <vector>
#include <iostream>
class Bar
{
private:
std::vector<int> intVector_;
public:
Bar() {};
void addInt(int newInt)
{
intVector_.push_back(newInt);
std::cout << intVector_.size() << " ";
};
int getIntVectorSize() { return intVector_.size(); };
};
class Foo
{
private:
Bar bar_;
public:
Foo() { bar_ = Bar(); };
Bar getBar() { return bar_; };
};
int main(char argc, char* argv[])
{
Foo foo = Foo();
foo.getBar().addInt(1);
std::cout << foo.getBar().getIntVectorSize() << " ";
foo.getBar().addInt(2);
std::cout << foo.getBar().getIntVectorSize() << " ";
foo.getBar().addInt(3);
std::cout << foo.getBar().getIntVectorSize() << " ";
}
My problem is that adding an int to the vector only seems to last for the duration of addInt(). My output for the size of the vector looks like this:
1 0 1 0 1 0
I'm rather new to C++ and all this reference/pointer business, so I am stumped as to how I can fix this, or if this is even possible. Thanks for any help!
It's because getBar() returns a Bar by value, which makes a copy of bar_ for every call of the function, and you are modifying the vector of the temporary.
You can avoid this by returning a reference:
class Foo
{
private:
Bar bar_;
public:
Foo() { bar_ = Bar(); }; // you prob. want to use an initialiser list btw.
Bar& getBar() { return bar_; };
// ^ notice the ampersand
};
This way, any modifications done on the return value of getBar are done on bar_ and not a temporary copy that is destroyed at the end of the statement.
Related
I want to call a method for all objects in a class at once. What's the simplest way to do that?
Also, how do I call a method for some, but not all objects in a class?
You could do something like this. The object constructor puts the object pointer into a set and the destructor removes them from the set. The set contains pointers to all living objects.
It's pretty self explanatory:
#include <iostream>
#include <set>
class Foo
{
static std::set<Foo*> FooObjects; // set of all Foo objects
int value = 0;
void Register(Foo*);
void UnRegister(Foo* f);
public:
Foo();
Foo(int v);
~Foo();
static std::set<Foo*>& FooSet();
void Display();
void Multiply(int multiplicator);
};
std::set<Foo*> Foo::FooObjects;
std::set<Foo*>& Foo::FooSet()
{
return FooObjects;
}
void Foo::Register(Foo* f)
{ // register an object
FooObjects.insert(f);
}
void Foo::UnRegister(Foo* f)
{
// unregister an object
FooObjects.erase(f);
}
Foo::~Foo()
{
UnRegister(this);
}
Foo::Foo()
{
Register(this);
}
Foo::Foo(int value) : value(value)
{
Register(this);
}
void Foo::Multiply(int multiplicator)
{
value *= multiplicator;
}
void Foo::Display()
{
std::cout << "Foo: " << value << "\n";
}
void SomeFunction()
{
Foo farray[10];
}
int main()
{
Foo f1;
Foo F2(2);
Foo F3(3);
SomeFunction(); // 10 Foo objects are created in SomeFunction
// but they are destroyed right after and therefore
// they never show up below.
// Display all Foo objects
for (const auto& object : Foo::FooSet())
object->Display();
// Multiply all foo objects by 2
for (auto& object : Foo::FooSet())
object->Multiply(2);
std::cout << "\n";
// Display all Foo objects
for (const auto& object : Foo::FooSet())
object->Display();
}
Possible output:
Foo: 3
Foo: 2
Foo: 0
Foo: 6
Foo: 4
Foo: 0
Default constructor shouldn't zero out any data member. But in some situation, it seems not to be like this.
The code example is brief.
#include <iostream>
using namespace std;
class Foo {
public:
int val;
Foo() = default;
};
int main() {
Foo bar;
if (bar.val != 0) {
cout << "true" << endl;
} else {
cout << "false" << endl;
}
return 0;
}
As excepted, above program outputs:
true
However, if a print statement for bar's data member added, the var member will be initialized to zero:
...
int main() {
Foo bar;
cout << bar.val << endl;
...
}
The outputs will be:
0
false
Similarly, if adding virtual function and destructor to the class Foo:
#include <iostream>
using namespace std;
class Foo {
public:
virtual void Print() {}
~Foo() {}
int val;
Foo() = default;
};
int main() {
Foo bar;
if (bar.val != 0) {
cout << "true" << endl;
} else {
cout << "false" << endl;
}
return 0;
}
or just init bar object:
class Foo {
public:
int val;
Foo() = default;
};
int main() {
Foo bar = Foo();
...
}
outputs with:
false
So what‘s the cause that influence the data member value of class? Shouldn't all of this test outputs with true?
As default initialization in this case:
otherwise, nothing is done: the objects with automatic storage duration (and their subobjects) are initialized to indeterminate values.
Note that indeterminate value includes 0, which is a valid result too. BTW reading these indeterminate values leads to UB.
This question already has answers here:
Does a const reference class member prolong the life of a temporary?
(6 answers)
Closed 4 years ago.
After encountering a similar situation in a real-world application I decided to put together a demo which shows that if I store derived classes as a pointer to the base class, and call a virtual method the behavior of the derived class will be incorrect. See the code below:
struct IntWrapper { int value; };
struct Base {
virtual ~Base() = default;
virtual void myMethod() = 0;
};
struct Foo : public Base {
const IntWrapper& x;
Foo(const IntWrapper& x) : x(x) {}
void myMethod() override {
std::cout << std::to_string(x.value) << std::endl;
}
};
struct Bar : public Base {
const IntWrapper& x;
const IntWrapper& y;
Bar(const IntWrapper& x, const IntWrapper& y) : x(x), y(y) {}
void myMethod() override {
std::cout << std::to_string(x.value) << " " << std::to_string(y.value) << std::endl;
}
};
int main()
{
Base* foo = new Foo(IntWrapper{3});
Base* bar = new Bar(IntWrapper{5}, IntWrapper{42});
foo->myMethod();
bar->myMethod();
return 0;
}
The expected output would be:
3
5 42
Instead I receive:
42
5 42
Interestingly, if I replace IntWrapper reference with a primitive int in the classes Foo and Bar the printed values will be correct. Can somebody explain to me why this behavior happens?
Base* foo = new Foo(IntWrapper{3});
Base* bar = new Bar(IntWrapper{5}, IntWrapper{42});
You're creating an IntWrapper temporary that you're passing as a reference to the constructors, that save that reference for later use. As the temporary gets destructed after the constructor, your references inside foo and bar are invalid, and you're invoking undefined behavior, meaning anyhting can happen.
You need to either create IntWrapper variables that you will pass to the constructors, like so:
IntWrapper x{3};
IntWrapper y{5};
IntWrapper z{42};
Base* foo = new Foo(x);
Base* bar = new Bar(y,z);
Or your classes should make copies of passed IntWrappers, instead of holding a reference to them.
All of your member references are dangling, hence you have UB. – Passer By
and
Base* foo = new Foo(IntWrapper{3}); creates a temporary IntWrapper (destroyed at the end of the full expression); you save a reference to this temporary in foo. When you next use foo the saved reference is dangling (as the temporary has been destroyed) and you have Undefined Behaviour. - Richard Critten
I added a little bit printf debugging to the sample code of OP for demonstration. Now, the effects described in comments become quite obvious (IMHO):
#include <iostream>
struct IntWrapper {
int value;
IntWrapper(int value): value(value)
{
std::cout << "IntWrapper::IntWrapper(" << value << ")\n";
}
~IntWrapper()
{
std::cout << "IntWrapper::~IntWrapper(" << value << ")\n";
}
};
struct Base {
Base(const char *text)
{
std::cout << text << "::" << text << "()\n";
}
virtual ~Base() = default;
virtual void myMethod() = 0;
};
struct Foo : public Base {
const IntWrapper& x;
Foo(const IntWrapper& x): Base("Foo"), x(x) { }
void myMethod() override {
std::cout << std::to_string(x.value) << std::endl;
}
};
struct Bar : public Base {
const IntWrapper& x;
const IntWrapper& y;
Bar(const IntWrapper& x, const IntWrapper& y): Base("Bar"), x(x), y(y) {}
void myMethod() override {
std::cout << std::to_string(x.value) << " " << std::to_string(y.value) << std::endl;
}
};
int main()
{
Base* foo = new Foo(IntWrapper{3});
Base* bar = new Bar(IntWrapper{5}, IntWrapper{42});
std::cout << "foo->myMethod();\n";
foo->myMethod();
std::cout << "bar->myMethod();\n";
bar->myMethod();
return 0;
}
Output:
IntWrapper::IntWrapper(3)
Foo::Foo()
IntWrapper::~IntWrapper(3)
IntWrapper::IntWrapper(5)
IntWrapper::IntWrapper(42)
Bar::Bar()
IntWrapper::~IntWrapper(42)
IntWrapper::~IntWrapper(5)
foo->myMethod();
3
bar->myMethod();
5 42
Live Demo on coliru
Note:
The fact that the sample matched the expected output should not be mis-interpreted. It's still undefined behavior.
I am trying to associate a struct's member variable with a class. So that when I create a new class, I can specify that it is associated with this member variable in a struct. For example:
struct A {
int a;
int b;
};
static A a[2];
a[0].a = 1;
a[0].b = 2;
a[1].a = 3;
a[1].b = 4;
class foo {
public:
foo(int index, ???) {
c = a[index].???; //Is it possible to define the 2nd parameter as a getter of struct A's member? So this line could resolve to either a[index].a or a[index].b?
}
private:
int c;
};
So that:
new foo(0, ???) would set c to 1 given ??? refer to A::a
new foo(0, ???) would set c to 2 given ??? refer to A::b
new foo(1, ???) would set c to 3 given ??? refer to A::a
new foo(1, ???) would set c to 4 given ??? refer to A::b
Yes, it is possible, you need to pass a data member pointer:
#include <iostream>
struct A
{
int a;
int b;
};
static A a[2]
{
1, 2
, 3, 4
};
class foo
{
public: int c;
public:
foo(int const index, int A::* const p_field)
{
c = a[index].*p_field;
}
};
int main()
{
foo const f1(0, &A::a);
::std::cout << f1.c << ::std::endl;
foo const f2(0, &A::b);
::std::cout << f2.c << ::std::endl;
foo const f3(1, &A::a);
::std::cout << f3.c << ::std::endl;
foo const f4(1, &A::b);
::std::cout << f4.c << ::std::endl;
return 0;
}
Check this code at online compiler
You have a couple options. If you just want the integer (like you have in your code you've posted), then just take an integer as a parameter to the constructor and pass it the right number.
class foo {
public:
foo(int val) {
c = val
}
private:
int c;
};
int main() {
foo f(a[0].b);
}
Or you could take a reference to an integer. This way if one changes, the other will as well:
class foo {
public:
foo(int &val) : c(val) { } //need to use an initialization list for this one
private:
int &c;
};
int main() {
foo f(a[0].b);
a[0].b = -1; //f.c will be -1 now as well
}
Using a data member pointer as in VTT's answer is the most direct solution but I often find member pointers and member function pointer syntax a bit cumbersome and I believe it is hard for the compiler to optimize.
For these kind of things I prefer to use a stateless lambda. You can pass a lambda to a function template and then the compiler can easily optimize it away:
#include <iostream>
struct A {
int a;
int b;
};
static A a[2]{{1, 2}, {3, 4}};
class foo {
public:
int c;
public:
template<typename F>
foo(int index, F getter) { c = getter(a[index]); }
};
int main() {
auto agetter = [](const A& a){ return a.a; };
auto bgetter = [](const A& a){ return a.b; };
foo const f1(0, agetter);
std::cout << f1.c << "\n";
foo const f2(0, bgetter);
std::cout << f2.c << "\n";
foo const f3(1, agetter);
std::cout << f3.c << "\n";
foo const f4(1, bgetter);
std::cout << f4.c << "\n";
}
I am writing code to access private members of a class through another friend class. The below code works
// Example program
#include <iostream>
#include <string>
using namespace std;
class Foo
{
private:
int a;
protected:
public:
friend class Bar;
Foo(int x)
{
a = x ;
}
};
class Bar
{
private:
protected:
public:
int b;
Bar(Foo& f)
{
b = f.a;
cout << "f.a is " << f.a << endl;
}
};
int main()
{
Foo foo(5);
Bar bar(foo);
cout << "Value of variable b is " << bar.b << endl;
}
Above code works fine. However, if I want to access a private variable of Foo through a function in friend class Bar, I am unable to. See code below
#include <iostream>
#include <string>
using namespace std;
class Foo
{
private:
int a;
protected:
public:
friend class Bar;
Foo(int x)
{
a = x ;
}
};
class Bar
{
private:
protected:
public:
int b;
Bar(Foo& f)
{
b = f.a;
}
void printvariable(void)
{
cout << "f.a is " << f.a << endl;
}
};
int main()
{
Foo foo(5);
Bar bar(foo);
cout << "Value of variable b is " << bar.b << endl;
}
I totally understand why execution fails on the
void printvariable(void)
{
cout << "f.a is " << f.a << endl;
}
function since f is not in scope for the function. However, since I am passing Foo f in the constructor for Bar b, I am hoping to write code that will allow me to access members in Foo without passing Foo f to the function printvariable() again.
What is the most efficient way to write this code?
You can keep the reference to f. The code should be:
class Bar
{
private:
protected:
public:
int b;
Foo& f_ref;
Bar(Foo& f)
:f_ref(f)
{
b = f.a;
}
void printvariable(void)
{
cout << "f.a is " << f_ref.a << endl;
}
};
TEST!
You can do it like this, but if I were you I'd write some getters, also – class friendship isn't really recommended.
class Bar {
public:
Foo& ref;
Bar(Foo& f)
: ref { f }
{ }
void printvariable() {
cout << "f.a is " << ref.a << endl;
}
};
Btw there's no reason to add void in brackets in C++, it lost its meaning from C and has no effect by now.
You are wrong in one point. You are indeed passing a reference to f in the ctor, but the constructor and whole class Bar does not remember a whole object of f. In your original code, the constructor only makes the Bar object remember the int a part of the object, so only that little bit is later accessible:
class Foo
{
...
friend class Bar;
...
};
class Bar
{
...
int b;
Bar(Foo& f)
{
b = f.a; // <=--- HERE
}
void printvariable(void)
{
cout << "f.a is " << b << endl; // <-- now it refers B
}
Please note how your ctor of Bar only reads f.a and stores it in b. From now on, the Bar object only remembers b and that's all. You can freely access the b in printvariable. However, it will not be the a-taken-from-f. It will be b, that was set to the same value as f.a during constructor. Since that point of time, b and f.a are totally separate. That's how value copying works.
To make Bar remember whole f, you have to, well, remember whole f:
class Bar
{
...
Foo wholeThing;
Bar(Foo& f)
{
wholeThing = f; // <=--- HERE
}
void printvariable(void)
{
cout << "f.a is " << wholeThing.a << endl;
}
However, again, there's a catch: now since wholeThing is of type Foo, the constructor will actually make a copy of that object during wholeThing=f. Just the same as it was when b=f.a, but now it remembers a copy of whole f.
Of course, it's only matter of type. You can store a reference instead of whole-Foo, but it needs a bit different initialization syntax:
class Bar
{
...
Foo& wholeThing;
Bar(Foo& f) :
wholeThing(f) // <=--- HERE
{
// <=--- empty
}
void printvariable(void)
{
cout << "f.a is " << wholeThing.a << endl;
}