Is it possible to default-initialize a temporary variable? - c++

Consider this code:
struct S { int m; };
S trick() { S s; return s; }
void bar(S s) { /* observe s.m */ }
void foo()
{
S s; // s.m is indeterminate
S* p = new S; // p->m is indeterminate
bar(S()); // bar() will observe S::m to be 0
bar(trick()); // bar() will observe S::m to be indeterminate
}
Is it possible to construct a temporary variable of type S without resorting to tricks?
Why do I need this?
As I understand "default initialization" is conceptually the cheapest way to construct an object. Ability to construct a temporary in such way can be useful to ignore data you don't need with as little of overhead as possible:
struct S { int m; };
void foo(S* pOut); // 3rd party function that insists on returning some data
template<class T> T* tmp_addr(T&& v) { return &v; } // careful with this one...
foo( tmp_addr(trick()) ); // receive and discard data without zeroing out memory

You can default initialize a sub-object of a temporary variable.
template<typename T>
class default_init_tmp final {
T t;
public:
default_init_tmp () /*Intentionally left blank*/ {}
default_init_tmp (default_init_tmp const&) = delete;
void operator=(default_init_tmp const&) = delete;
T* operator&() { return &t; }
};
Granted, usually it's ill-advised to overload operator&, but it somehow seems appropriate here, given the general nature of the exercise. You'd use it as follows
int main()
{
foo(&default_init_tmp<S>());
}

How about:
#include <memory>
struct Foo
{
int i;
};
auto trick() {
return std::make_unique_for_overwrite <Foo>(); // C++20
// return std::unique_ptr<Foo>(new Foo); // pre C++20
}
void foo(Foo* f);
int main()
{
foo(trick().get());
}

Is it possible to default-initialize a temporary variable?
I don't think so.
Also, the behaviour of your program is undefined, because it reads (copies) indeterminate values. A simple, and correct way to use foo without value initialisation is to not use a temporary:
S s;
foo(&s);

Related

How to return a class instance on the heap, when the relevant ctor is private?

Suppose I have this struct
struct MyStruct {
static MyStruct Create(int x) {
return { x*2, x>3 };
}
MyStruct(const MyStruct& c) = delete; // no copy c'tor
private:
MyStruct(int a_, bool b_) : a(a_), b(b_) {} // private c'tor -- can't use new
const int a;
const bool b;
};
Edit: I deleted the copy constructor. This is simplified example of some classes I have in my codebase where they don't have copy c'tors.
I can get an instance on the stack like so:
int main() {
auto foo = MyStruct::Create(2);
return 0;
}
But suppose I need a pointer instead (or unique_ptr is fine), and I can't change the implementation of MyStruct, how can I do that?
You could wrap MyStruct in another class, which has a MyStruct member. Here's a minimal version of that:
class Wrapper {
public:
MyStruct ms;
Wrapper(int x) : ms(MyStruct::Create(x)) { }
};
which you can use like so:
int main() {
MyStruct::Create(2);
std::make_unique<Wrapper>(2);
}
This code will not trigger any copies nor moves - because of copy elision (see: What are copy elision and return value optimization?).
You can then add any other constructors and methods you like to such a wrapper, possibly forwarding some of the method calls to the ms member. Some might choose to make ms protected or private.
Is this what you're looking for?
auto baz = std::make_unique<MyStruct>( MyStruct::Create(2) ); // unique pointer
A comment rather than an answer, to avoid confusion for future readers.
I can get an instance on the stack like so:
int main() {
auto foo = MyStruct::Create(2);
return 0;
}
Note that this is only true as of C++17 and guaranteed copy elision, whereas the program is ill-formed is C++14, as even if the copy may be elided, the initialization of foo is copy-initialization from a temporary (in C++17: the temporary is never materialized).
One more way to do it:
struct ChildStruct : public MyStruct {
ChildStruct(int x) : MyStruct(MyStruct::Create(x))
{}
};
int main() {
MyStruct *foo1 = new ChildStruct(2);
return 0;
}
C style solution. I am not sure that this is not UB, but for simple struct with 2 integer fields it should work.
int main() {
auto foo = MyStruct::Create(2);
MyStruct *p = (MyStruct*)malloc(sizeof(MyStruct));
memcpy(p, &foo, sizeof(MyStruct));
//...
free(p);
return 0;
}

How to extend lifetime of member reference?

Example code:
#include <iostream>
using namespace std;
struct Data {
int d;
};
class Foo {
public:
explicit Foo(const Data& data) : data_(data) {}
void PrintData() {
std::cout << data_.d << std::endl;
}
private:
const Data& data_;
};
Foo CreateFoo(int i) {
Data d;
d.d = i;
return Foo(d);
}
int main() {
Foo foo = CreateFoo(5);
foo.PrintData(); // prints 0 instead of 5
return 0;
}
https://ideone.com/KpCstl
foo.data_ is a reference to the Data created in CreateFoo which goes out of scope at the end of the function.
Without changing the definition of class Foo (e.g. to remove the reference), how can I extend the lifetime of d/data_, preferably so that it matches the lifetime of the Foo instance?
Is there perhaps some container object that I can wrap Foo in that will keep all its deps alive and return that from CreateFoo instead?
In the actual usage, our framework will keep Data alive, so it will outlive Foo as intended. But for my test code, I need to find another mechanism to keep Data alive at least until the test run is complete. I can use some kind of singleton to keep it alive, but I'm looking for a cleaner solution.
If you want to keep the reference in the member variable, then likely you will need to use dynamic allocation. Think about it -- the reference must point to some Data object somewhere that has the same lifetime as the Foo, but the Data object can't be stored with the Foo object, as the Foo object has no space for it, only for a reference. So generally in this case it is allocated on the heap. I would suggest using a unique_ptr to automatically manage this Data object:
#include <iostream>
#include <memory>
using namespace std;
struct Data {
int d;
};
class Foo {
public:
explicit Foo(const Data& data) : data_(std::make_unique<Data>(data)) {}
void PrintData() {
std::cout << data_->d << std::endl;
}
private:
std::unique_ptr<Data> data_;
};
Foo CreateFoo(int i) {
Data d;
d.d = i;
return Foo(d);
}
int main() {
Foo foo = CreateFoo(5);
foo.PrintData();
return 0;
}
Note that a unique_ptr allows only for one object to have ownership, which will disallow Foos from being copied unless you override the relevant methods. If you want copied Foos to have references to the same object, use shared_ptr and make_shared instead. If you want copied Foos to copy their Data objects, overload the copy constructor and operator=, or better yet, turn the Data pointer into a plain Data member.
If you don't want to have Foos own and manage their Datas, then I would suggest:
#include <iostream>
#include <memory>
using namespace std;
struct Data {
int d;
};
class Foo {
public:
explicit Foo(Data& data) : data_(data) {}
void PrintData() {
std::cout << data_->d << std::endl;
}
private:
Data& data_;
};
struct FooWithData {
Data foo_data;
Foo foo;
FooWithData(const FooWithData& other)
: foo_data(other.foo_data),
foo(foo_data) {}
FooWithData(FooWithData&& other)
: foo_data(other.foo_data),
foo(foo_data) {}
FooWithData& operator=(FooWithData& other) {
foo_data = other.foo_data;
}
};
FooWithData CreateFoo(int i) {
FooWithData ret;
ret.foo_data = Data { i };
ret.foo = Foo(ret.foo_data);
return ret;
}
int main() {
FooWithData foo_compound = CreateFoo(5);
foo_compound.foo.PrintData();
return 0;
}
This solution should work for you:
Foo CreateFoo(int i) {
static std::forward_list<Data> v;
v.push_front(Data{i});
return Foo(v.front());
}
Maintain a static container of Data objects, add a new object on every call to CreateFoo, and hand out references to the last inserted object.
Since the container is static you won't have lifetime issues. Also, a container of objects ensures that every call returns a Foo that binds to a unique Data object.
Also, note that you need a container that doesn't invalidate references to it on modification, so I chose std::forward_list.
Here's a demo.
If you want to keep your element alive even after scopes ends then you should use pointer, but again raw pointer is dangerous, so to counter this use std::shared_ptr, but then you wont be able to use ref variable to shared_ptr but an actual shared_ptr variable to keep the object of Data alive.
struct Data{
int data;
};
class Foo{
public:
explicit Foo(std:shared_ptr<Data>) {data = _data;}
Foo createFoo(){
shared_ptr<Data> d(new Data);
return Foo(d);//this thing makes sure your shared pointer gets copied and it does not go out of scope
}
std::shared_ptr<Data> data;
};

My lambda does not correctly convert the captured 'this' during copy construction

I've narrowed down my problem to exactly this
#include <iostream>
#include <functional>
struct Foo {
std::function<Foo*()> lambda;
Foo()
:lambda([this](){return this;})
{}
};
int main(){
Foo a;
Foo b = a;
std::cout << &a << " " << a.lambda() << std::endl;
std::cout << &b << " " << b.lambda() << std::endl;
}
where the output is
0x7ffd9128b8a0 0x7ffd9128b8a0
0x7ffd9128b880 0x7ffd9128b8a0
I originally expected that this would always point to the instance that owned the lambda. However I forgot about copy construction. In this case the lambda captures this and then it is fixed and no matter how many times the lambda is copied it points to the original value of this.
Is there a way fix this so that lambda always has a reference to it's owning object this even under copy construction of the owning object.
Sounds like you need to provide your own special member functions, no? E.g., for the copy constructor:
Foo(const Foo& other)
:lambda([this](){return this;})
{}
Whilst #lubgr answered the question for what I asked I think it is worth noting the other solution I have for my exact problem. The question stemmed from building a class to encapsulate lazy initialisation of members. My original attempt was
template <typename T>
class Lazy {
mutable boost::once_flag _once;
mutable boost::optional<T> _data;
std::function<T()> _factory;
void Init() const { boost::call_once([&] { _data = _factory(); }, _once); }
public:
explicit Lazy(std::function<T()> factory):_once(BOOST_ONCE_INIT),_factory(factory){}
T& Value() {
Init();
return *_data;
}
};
which can be used like
class Foo {
int _a;
Lazy<int> _val;
Foo(a):_a(a):_val([this](){return this->_a+1;}){}
}
Foo f(10);
int val = f._val.Value();
but has the same problem that I asked in my question in that this is a circular reference that doesn't get preserved for copy construction. The solution is not to create a custom copy constructor and possibly move constructor but to fix the Lazy implementation class so that we can pass in an arg to the factory.
The new implementation of Lazy for members is
template <typename T, typename TThis>
class LazyMember {
mutable boost::once_flag _once;
mutable boost::optional<T> _data;
typedef std::function<T(TThis const*)> FactoryFn;
FactoryFn _factory;
void Init(TThis const * arg0) const { boost::call_once([&] { _data = _factory(arg0); }, _once); }
public:
explicit LazyMember(FactoryFn factory):_once(BOOST_ONCE_INIT),_factory(factory){}
T& Value(TThis const * arg0) { Init(arg0); return *_data; }
T const & Value(TThis const * arg0) const { Init(arg0); return *_data; }
};
which is used as
class Foo {
int _a;
Lazy<int> _val;
Foo(a):_a(a):_val([](Foo const * _this){return _this->_a+1;}){}
}
Foo f(10);
int val = f._val.Value(&f);
and this doesn't have the circular reference problems and thus doesn't require a custom copy/move constructor.

C++: Keeping rvalue reference implicitly for fields of a smart pointer

Let f() be a function that returns a unique_ptr<X> and let m be a member field of X. While f() can be used as an rvalue reference, f()->m cannot, forcing me to use move(f()->m).
Assuming that I can define my own unique_ptr instead of using the existing one, is there a way to make my -> operator keep the rvalue-ness? If this is not recommended, please explain why.
EDIT: To all people telling me to add a getter. I am trying to avoid adding special support in X, I want to do it through the unique_ptr only. Also, your solution can be improved by using a right reference for this as in the following example:
struct X {
SomeType m;
const SomeType &getM() const { return m; }
SomeType &&getM() && { return move(m); }
SomeType &getM() { return m; }
}
As long as you are accessing the value m by name, this can never be an r-value without casting. You could however add a member function which "moves" the member value out of your object.
using IntPtr = std::unique_ptr<int>;
class X {
IntPtr m;
public:
X();
IntPtr getM() { return std::move(m); }
}
Hide the move... (undeleted as I think this could be one way of solving it without having to have your own custom unique_ptr) and I guess it's in keeping with encapsulation...
#include <memory>
#include <iostream>
struct foo
{
std::string m;
std::string m_()
{ return std::move(m); }
};
std::unique_ptr<foo> get_foo()
{ return std::unique_ptr<foo>(new foo{ "Bar" }); }
void bar(std::string&& r)
{ std::cout << r << std::endl; }
int main()
{
// bar(get_foo()->m); // this does not compile
bar(get_foo()->m_()); // this is happy...
}
Now you should be good to go...

Is this valid C++ code according to standard?

I have this sample code:
struct A
{
bool test() const
{
return false;
}
};
template <typename T = A>
class Test
{
public:
Test(const T& t = T()) : t_(t){}
void f()
{
if(t_.test())
{
//Do something
}
}
private:
const T& t_;
};
int main()
{
Test<> a;
a.f();
}
Basically I am worried about the constructor of Test where I am storing a const reference to a temporary variable and using it in methof f. Will the temporary object reference remains valid inside f ?
It won't remain valid. The temporary object will be destroyed after initializing a. At the time you call f you invoke undefined behavior by calling test. Only the following is valid:
// Valid - both temporary objects are alive until after the
// full expression has been evaluated.
Test<>().f();