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.
Related
A performance bottleneck of my program is frequent calls to functions like following update functions.
Given that flag parameter is always a bool literal, I want to "unroll" the update function to two versions, one with flag=true and one with flag=false, to avoid branch prediction failure.
for normal functions, a bool template parameter can solve this problem easily.
However, template cannot be applied to virtual functions.
I can create two virtual functions manually, but then I have to copy the long code part. It makes futher development harder.
Is there anyway allowing me to write two versions in one function, controlled by a compiling-time constant flag?
#include <iostream>
#include <random>
using std::cout;
using std::endl;
struct Base
{
virtual void update(bool flag) = 0;
};
struct Derived1 : public Base
{
void update(bool flag)
{
if (flag)
{
// some computations
cout << "Derived1 flag=true" << endl;
}
else
{
// some computations
cout << "Derived1 flag=false" << endl;
}
// long code containing several flag-conditioned blocks like the block above
cout << "Derived1" << endl;
}
};
struct Derived2 : public Base
{
void update(bool flag)
{
if (flag)
{
// some computations
cout << "Derived2 flag=true" << endl;
}
else
{
// some computations
cout << "Derived2 flag=false" << endl;
}
// long code containing several flag-conditioned blocks like the block above
cout << "Derived2" << endl;
}
};
int main()
{
Base *p;
srand(time(nullptr));
if (rand() % 2 == 1)
{
p = new Derived1();
}
else
{
p = new Derived2();
}
p->update(false);
p->update(true);
}
Unfortunately, there is no such thing as virtual templates. What can be done however is to create several virtual functions taking an integral (boolean in this particular case) constant, if the flag is really a compile time literal:
#include <iostream>
#include <random>
#include <type_traits>
#include <memory>
using std::cout;
struct Base
{
virtual void updateSeparate(std::true_type) = 0;
virtual void updateSeparate(std::false_type) = 0;
};
struct Derived1 : public Base
{
void updateSeparate(std::true_type)
{
cout << "Derived1 flag=true\n";
updateCommonImpl();
}
void updateSeparate(std::false_type)
{
cout << "Derived1 flag=false\n";
updateCommonImpl();
}
private:
void updateCommonImpl() //or just a static function inside implementation file if members are not used
{
cout << "Derived1\n";
}
};
struct Derived2 : public Base
{
void updateSeparate(std::true_type)
{
cout << "Derived2 flag=true\n";
updateCommonImpl();
}
void updateSeparate(std::false_type)
{
cout << "Derived2 flag=false\n";
updateCommonImpl();
}
private:
void updateCommonImpl() //or just a static function inside implementation file if members are not used
{
cout << "Derived2\n";
}
};
int main()
{
std::unique_ptr<Base> p;
srand(time(nullptr));
if (rand() % 2 == 1)
{
p = std::make_unique<Derived1>();
}
else
{
p = std::make_unique<Derived2>();
}
p->updateSeparate(std::bool_constant<false>{});
p->updateSeparate(std::bool_constant<true>{});
}
DEMO
However, I cannot tell if that will help or maybe hinder the performance even more by making the vtable lookup time even longer, you have to experiment with that by yourself I'm afraid.
I tried to implement a CRTP pattern with constexpr template parameter, please take a look
template<typename T>
struct Base {
template<bool flag>
int update() {
return static_cast<T*>(this)->template updateImpl<flag>();
}
};
struct Derived1 : public Base<Derived1> {
template<bool flag>
constexpr int updateImpl() {
if constexpr (flag) {
return 1;
} else {
return 2;
}
}
};
struct Derived2 : public Base<Derived2> {
template<bool flag>
constexpr int updateImpl() {
return 3;
}
};
int main() {
auto obj1 = new Derived1();
std::cout << obj1->update<true>(); // 1
std::cout << obj1->update<false>(); // 2
auto obj2 = new Derived2();
std::cout << obj2->update<true>(); // 3
std::cout << obj2->update<false>(); // 3
}
I meet a course programming problem, which asks me to initialize the A a using passing by reference (initialize the A a in the func). How can I call A's constructor by A's reference?
#include <iostream>
using namespace std;
class A
{
public:
int x;
A()
{
cout << "default constructor" << endl;
x = 1;
}
A(int x)
{
cout << "constructor with param = " << x << endl;
this->x = x;
}
~A() {
cout << "destructor" << endl;
}
void print() {
cout << x << endl;
}
};
void fun(A& a)
{
a.A::A(10); // error!
return;
}
int main()
{
A a;
fun(a);
a.print();
return EXIT_SUCCESS;
}
There is a background of this problem. The teacher want us to replicate the NRVO(named return value optimization) result.
#include <iostream>
using namespace std;
class A
{
public:
int x;
A()
{
cout << "default constructor" << endl;
x = 1;
}
A(int x)
{
cout << "constructor with param = " << x << endl;
this->x = x;
}
~A() {
cout << "destructor" << endl;
}
void print() {
cout << x << endl;
}
};
A fun() {
A a = A(10);
return a;
}
int main()
{
A a = fun();
return EXIT_SUCCESS;
}
default g++ compiler:
constructor with param = 10
destructor
if we close the NRVO:
g++ test.cpp -fno-elide-constructors
constructor with param = 10
destructor
destructor
destructor
destructor
The teacher want us to replicate the NRVO(named return value optimization) result by passing by reference.
The syntax a.A::A(10); is incorrect.
Constructor is used to create an object of a class, you cannot call it on an already existing object. Even a constructor cannot be explicitly called. It is implicitly called by the compiler.
From general-1.sentence-2:
Constructors do not have names.
Thus, you cannot call a constructor explicitly. The compiler will automatically call the constructor when an object of that class-type is created.
You can not, not like this.
A reference always points to an initialized object. So you already failed before you called the function. The "return" argument is already initialized. And you can't initialized an initialized value again, not legally.
You can cheat by calling
std::construct_at(&a, 10);
For it to really reflect NRVO you could have something like this:
void fun(A *a)
{
std::construct_at(a, 10);
}
union UninitializedA {
std::byte uninitialized[sizeof(A)];
A a;
};
int main()
{
UninitializedA u;
fun(&u.a);
u.a.print();
u.a.~A();
return EXIT_SUCCESS;
}
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;
}
I recently read simple STL sources,Here is the code:
#include <iostream>
#include <cstddef>
using namespace std;
class alloc
{
};
template <typename T, typename Alloc = alloc, size_t Bufsiz = 0>
class deque
{
public:
deque() { cout << "deque()" << endl; }
};
template <typename T, typename Sequence = deque<T> >
class stack
{
public:
stack() { cout << "stack()" << endl; }
private:
Sequence c;
};
int main()
{
stack<int> x;
return 0;
}
The output:
deque()
stack()
When i created a stack object,it should have called stack constructor first.But the fact is not.
Why the compiler calls deque constructor first?
Before you enter the body of a constructor, base class constructors are called, then all non-static member variables are default initialized in the order of declaration, unless they appear in a member initialization list. In your code Sequence c is initialized first and then the body of Stack::Stack() is executed.
This program illustrates the order of construction - destruction.
#include <iostream>
#include <string>
using namespace std;
struct Base_1
{
Base_1()
{
cout << "Base_1\n";
}
~Base_1()
{
cout << "~Base_1\n";
}
};
struct Base_2
{
Base_2()
{
cout << "Base_2\n";
}
~Base_2()
{
cout << "~Base_2\n";
}
};
struct Member_1
{
Member_1()
{
cout << "Member_1\n";
}
~Member_1()
{
cout << "~Member_1\n";
}
};
struct Member_2
{
Member_2()
{
cout << "Member_2\n";
}
~Member_2()
{
cout << "~Member_2\n";
}
};
struct Member_non_default
{
Member_non_default( string s )
{
cout << "Member non default\n";
}
~Member_non_default()
{
cout << "~Member non default\n";
}
};
struct Static_member
{
Static_member()
{
cout << "Static member\n";
}
~Static_member()
{
cout << "~Static member\n";
}
};
struct Derived: Base_1, Base_2
{
Member_1 m1;
Member_non_default m;
Member_2 m2;
static Static_member sm;
Derived():
m { "Member non default\n" }
{
cout << "Derived\n";
}
~Derived()
{
cout << "~Derived\n";
}
};
Static_member Derived::sm;
int main()
{
Derived d;
}
Output
Static member
Base_1
Base_2
Member_1
Member non default
Member_2
Derived
~Derived
~Member_2
~Member non default
~Member_1
~Base_2
~Base_1
~Static member
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.