I am learning C++14, in that come across this template variable feature and that interested me to dig more on this and i tried with multiple examples to understand the template variables. Say,
template <typename T>
T var;
var<int>;
var<float>;
Above code worked and it looked straight forward to understand too. But, when I tried to use class name in place of int or float as shown above, result in calling the temporary object creation for the class FOO and calling corresponding C'tor & dtor for the temp object.
var<FOO>; //FOO is a class
I have written a sample test program and its output for your understanding. My question is that,
Why var creates temp object?
How template variable differ for primitive datatypes and user defined datatypes?
If it is irrelevant or duplicate, please point me to the source for clear understanding.
Refer code below,
class B
{
public:
B()
{
std::cout<<"\nB ctor"<<std::endl;
}
B(const B& obj)
{
std::cout<<"B copy ctor"<<std::endl;
}
int operator()()
{
std::cout<<"operator() called"<<std::endl;
}
void f() {
//::A().print();
}
~B()
{
std::cout<<"\n~ for B()"<<std::endl;
}
};
//Declaring template variable
template<typename T>
T g ;
int main() {
g<int> = 30;
g<float> = 30.02f;
g<B> = B{};
std::cout<<"g value:"<<g<int><<std::endl;
std::cout<<"g value:"<<g<float>;
}
Output:
B ctor
g value:30
g value:30.02
~ for B()
No temporary object is created by this simple program:
int main() {
var<SomeClass>;
}
A temporary object is created here:
int main() {
var<SomeClass> = SomeClass{};
}
but that is because we did it with SomeClass{}. We then assigned that to the var<SomeClass> non-temporary object (global in many of your examples).
The code that runs here is
SomeClass::SomeClass()
SomeClass::SomeClass()
SomeClass::operator=(SomeClass&&)
SomeClass::~SomeClass()
SomeClass::~SomeClass()
in that order.
#include <iostream>
struct noisy {
noisy() { std::cout << __func__ << "()\n"; }
~noisy() { std::cout << __func__ << "()\n"; }
noisy(noisy&&) { std::cout << __func__ << "(&&)\n"; }
noisy(noisy const&) { std::cout << __func__ << "(c&)\n"; }
void operator=(noisy&&) { std::cout << __func__ << "(&&)\n"; }
void operator=(noisy const&) { std::cout << __func__ << "(c&)\n"; }
};
template<class T>
T var;
int main() {
std::cout << "Start of main\n";
{
var<noisy> = noisy{};
std::cout << "Body of main\n";
}
std::cout << "End of main\n";
}
live example.
Output:
noisy()
Start of main
noisy()
operator=(&&)
~noisy()
Body of main
End of main
~noisy()
Related
I'm struggling to understand the scope and ownership of lambda captures, why does the following code work?:
#include <iostream>
struct Foo {
void setCallback(std::function<void()> f) { callback = std::move(f); }
void trigger() { callback(); }
private:
std::function<void()> callback;
};
struct Bar {
int i;
Bar(int i) : i{i} { std::cout << "bar constructed" << std::endl; }
~Bar() { std::cout << "bar destroyed" << std::endl; }
};
int main() {
Foo foo{};
{ // scope
Bar bar{1};
foo.setCallback([&bar]() { std::cout << bar.i << std::endl; });
bar.i = 2;
} //end of scope, bar gets deleted
foo.trigger();
return 0;
}
Output:
bar constructed
bar destroyed
2
Is the compiler inlining bar.i in the lambda function statically? I'm capturing by reference, what is going on?
Hello Your code does not work because bar is descoped before the lambda that captured it is executed. The lambda uses a dangling reference. Here is an updated sample that will convince you, that if it works in your example it is simply because nothing else has been allocated at the address where bar was initially stored.
#include <iostream>
#include <functional>
struct Foo {
void setCallback(std::function<void()> f) { callback = std::move(f); }
void trigger() { callback(); }
private:
std::function<void()> callback;
};
struct Bar {
int i;
Bar(int i) : i{i} { std::cout << "bar constructed" << std::endl; }
~Bar() { std::cout << "bar destroyed" << std::endl; }
};
int main() {
Foo foo{};
{ // scope
Bar bar{1};
foo.setCallback([&bar]() { std::cout << bar.i << std::endl; });
bar.i = 2;
} //end of scope, bar gets deleted
volatile int a = 5; // allocate something after bar is destroyed
foo.trigger();
return 0;
}
Now you will get:
bar constructed
bar destroyed
5
5 is the next value allocated on the stack in place of bar.
The following code produces the output
outer::inner::inner, o=00000000
outer
outer::inner::val, o=00000000
outer::print
Can anyone explain how I can access the outer class method print through o without explicitly assigning o's value at construction?
Here o is null, but I can still invoke its methods.
I have tested this with MSVC 2017 and g++ 7.4.0 and the output is same.
#include <iostream>
class outer {
public:
outer() {
std::cout << __func__ << std::endl;
}
class inner {
outer *o = nullptr;
public:
inner() {
std::cout << __FUNCTION__ << ", o=" << o << std::endl;
}
void val() {
std::cout << __FUNCTION__ << ", o=" << o << std::endl;
o->print(); // **call outer class method**
}
};
inner i;
void print() {
std::cout << __FUNCTION__ << std::endl;
}
};
int main()
{
outer o;
o.i.val();
return 0;
}
You can simplify your example to
struct S
{
void f() { std::cout << "hello world\n"; }
};
int main()
{
S* s = nullptr;
s->f();
}
And dereferencing nullptr is UB. So anything can happen.
Why does it appear to work?
Because, in practice, method functions are generally implemented as if there were regular functions with extra parameter:
void S::f() -> void f(S*) (or void f(S&))
and so, code becomes:
void f(S* /*unused*/) { std::cout << "hello world\n"; }
int main()
{
S* unused = nullptr;
f(unused);
}
In that case, compiler transforms UB in valid code, as unused is not used, it doesn't crash and does what you expect.
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 found a problem while using 3rd party code which cannot be altered. I need to make a copy of object member. I can't do this strictly because one of inner members has private assignment operator. The only solution I found is tricky so I want to ask you if you see any red lights that can affect my program.
Here's the simplified code I'm dealing with (remember that I cannot change it!):
#include <iostream>
#include <algorithm>
class MBool
{
public:
MBool() {};
MBool(const MBool& arg) {}
private:
MBool& operator=(const MBool& arg);
};
class InnerContent {
private:
int* pBuffer;
public:
InnerContent() {
pBuffer = new int[20];
std::cout << "InnerContent()" << std::endl;
}
InnerContent(const InnerContent& otherInnerContent) {
pBuffer = new int[20];
std::copy(otherInnerContent.pBuffer, otherInnerContent.pBuffer + 20, pBuffer);
std::cout << "InnerContent(const InnerContent&)" << std::endl;
}
~InnerContent() {
std::cout << "~InnerContent()" << std::endl;
delete [] pBuffer;
pBuffer = nullptr;
}
virtual void someVirtualFunction() {}
};
class Content {
public:
InnerContent innerContent;
int someNumber;
MBool boolVar;
Content() {
std::cout << "Content()" << std::endl;
}
~Content() {
std::cout << "~Content()" << std::endl;
}
Content(const Content& otherContent) :
innerContent(otherContent.innerContent),
someNumber(otherContent.someNumber),
boolVar(otherContent.boolVar)
{
std::cout << "Content(const Content&)" << std::endl;
}
virtual void someVirtualFunction() {}
};
class A {
public:
Content content;
A() { std::cout << "A()" << std::endl; }
~A() { std::cout << "~A()" << std::endl; }
};
class B {
public:
Content content;
B() { std::cout << "B()" << std::endl; }
~B() { std::cout << "~B()" << std::endl; }
};
And here's what I'm about to do with it (only this code can be modified and extended):
void copyContent(Content& contentFrom, Content& contentTo) {
contentTo.~Content();
new (&contentTo) Content(contentFrom);
};
int main() {
A a;
B b;
// I wish to do this:
//b.content = a.content;
// but Content class has no operator= function implemented
// also I can't use generated assignment operator function because of MBool::operator= is private
// The only work-around I found is this:
std::cout << "--- Before copying" << std::endl;
copyContent(a.content, b.content);
std::cout << "--- After copying" << std::endl;
}
My solution is to call Content destructor manually to free any dynamically allocated memory in Content and its inner classes. Memory on the stack remains untouched so I can reuse it with placement-new operator that calls copy constructor that is present and does exactly what I need. When main function scope ends 'a' object is cleaned up properly.
Code output:
InnerContent()
Content()
A()
InnerContent()
Content()
B()
--- Before copying
~Content()
~InnerContent()
InnerContent(const InnerContent&)
Content(const Content&)
--- After copying
~B()
~Content()
~InnerContent()
~A()
~Content()
~InnerContent()
I don't want to make my own function that copies all the fields because this class can be updated in new version and there may be additional field that I will not copy and most probably no one will remember to fix it.
Question: Do you think this may cause any memory leaks or memory corruption? Do you see any problems that I didn't mention?
Basically the Idea should work. To protect yourself from forgetting to call the destructor, I think, you should wrap the whole think in a kind of smart pointer like class template. In this example it actually does not wrap a pointer, but the content object itself.
template <typename ContentType>
class content_wrapper {
private:
ContentType content_;
public:
content_wrapper() : content_ {} {};
content_wrapper(const content_wrapper& other) :
content_{other.content_} {};
content_wrapper& operator = (const content_wrapper& other) {
content_.~ContentType();
new (&content_) ContentType(other);
return *this;
}
ContentWrapper& operator * () {
return content_;
}
ContentWrapper* operator -> () {
return &content_;
}
};
now you can use it like that:
class A {
public:
content_wrapper<Content> content;
A() { std::cout << "A()" << std::endl; }
~A() { std::cout << "~A()" << std::endl; }
};
class B {
public:
content_wrapper<Content> content;
B() { std::cout << "B()" << std::endl; }
~B() { std::cout << "~B()" << std::endl; }
};
int main() {
A a;
B b;
b.content = a.content; // the wrapper will take care.
b.content->someVirtualFunction();
}
Easy to read and you can never forget the destructor call, whenever you want to assign a content object.
I'm trying to make a function that mimics Python's with statement but I've run into some interesting behavior that I don't quite understand.
With the following program:
#include <iostream>
struct foo {
foo() { std::cout << "foo()" << std::endl; }
~foo() { std::cout << "~foo()" << std::endl; }
};
auto make_foo() -> foo {
return {};
}
template <typename T, typename F>
auto with(T&& t, F&& fn) -> void {
fn(std::forward<T>(t));
}
auto main() -> int {
std::cout << "before" << std::endl;
with(make_foo(), [](auto f) {
std::cout << "during" << std::endl;
});
std::cout << "after" << std::endl;
}
When compiled under with the clang provided by Xcode 6.3 and -std=c++14 and run I get the following output:
before
foo()
during
~foo()
~foo()
after
Does anybody know why I am getting two ~foo()'s in my output?
Here are the two objects:
with(make_foo(), [](auto f) {
1^^^^^^^^^ 2^^^^^^
There is the object returned by make_foo(), and the function argument f.
If you pass by reference (change to auto&& f) then you will only see evidence of one object.
There's no creation message because this is created by copy/move construction and you do not have any output in those constructors.
Note that there may be more objects inside make_foo() but your compiler is doing copy elision.
Your destructor calls don't appear to be matched with constructor calls simply because you aren't tracing copy/move constructors. If we add the tracing like so:
struct foo {
foo() { std::cout << "foo()" << std::endl; }
~foo() { std::cout << "~foo()" << std::endl; }
foo(const foo&) { std::cout << "foo(const foo&)" << std::endl; }
foo(foo&&) { std::cout << "foo(foo&&)" << std::endl; }
};
our output is now:
before
foo()
foo(foo&&)
during
~foo()
~foo()
after
The reason for the move-construction is that your lambda takes its parameter by value:
[](auto f) {
// ^^^^^^
std::cout << "during" << std::endl;
}
If you don't want the copy, take by reference-to-const, or maybe even forwarding reference.
This works for me by accepting an r-reference in the lambda function parameter to prevent a copy being made:
#include <iostream>
struct foo {
foo() { std::cout << "foo()" << std::endl; }
~foo() { std::cout << "~foo()" << std::endl; }
};
auto make_foo() -> foo {
return {};
}
template <typename T, typename F>
auto with(T&& t, F&& fn) -> void {
fn(std::forward<T>(t));
}
auto main() -> int {
std::cout << "before" << std::endl;
with(make_foo(), [](auto&&) { // r-reference!
std::cout << "during" << std::endl;
});
std::cout << "after" << std::endl;
}
New Improved Output:
before
foo()
during
~foo()
after