C++ Smart Pointer Lost in std::make_unique - c++

I am in the process of converting some legacy code to take advantage of smart pointers in C++. However, I ran into a runtime issue that I'm struggling to figure out. I have code such as the following:
struct foo {
int field;
};
class SomeClass {
private:
std::unique_ptr<foo> m_Foo;
int m_Field;
public:
SomeClass(std::unique_ptr<int> ctorArg)
: m_Field(ctorArg->field), m_Foo(std::move(ctorArg)) {
}
};
std::unique_ptr<foo> fooPtr{ new foo() };
auto const classInstance{ std::make_unique<SomeClass>(std::move(fooPtr)) };
If I put a breakpoint prior to calling the SomeClass constructor, I can verify that fooPtr is not null. However, once I am within the SomeClass constructor, the application is crashing when trying to initialize m_Field, since ctorArg is null (empty). Is this expected? If I change the constructor signature to take std::unique_ptr<int> &&, I see the same issue. Can someone please explain what the issue is with this code, and how to go about fixing it?

The order of member-initializer-list is irrelevant, the members will be initialized in the order of their declaration.
So, first m_Foo(std::move(ctorArg)) will zero out ctorArg then m_Field(ctorArg->field) will attempt to derefence an empty ctorArg.
Change your code to:
class SomeClass {
private:
std::unique_ptr<foo> m_Foo;
int m_Field;
public:
SomeClass(std::unique_ptr<int> ctorArg)
: m_Foo(std::move(ctorArg)), m_Field(m_Foo->field) {
}
};
That is, always mention initializers in the order the fields are declared, and don't use input arguments which have been moved-out from.

Related

Aligned storage and standard layout

Consider the following C++11 code:
#include <type_traits>
struct bar
{
virtual void do_bar() const {}
};
struct foo
{
std::aligned_storage<sizeof(bar),alignof(bar)>::type m_storage;
};
bar is not standard layout because of the virtual function do_bar(). However, foo is standard layout as the type provided by std::aligned_storage is a POD type and foo satisfies all the other requirements for standard layout types.
What happens then when I use the m_storage storage with placement new to construct an instance of bar? E.g.,
foo f;
::new(static_cast<void *>(&f.m_storage)) bar();
Is this legal? Can I use this to cheat my way around restrictions about standard layout types?
Here's your code again:
struct bar {
virtual void do_bar() const {}
};
struct foo {
std::aligned_storage<sizeof(bar), alignof(bar)>::type m_storage;
};
This is fine. struct foo is a standard-layout type, and, given an instance foo myFoo, you can construct an object of type bar into myFoo.m_storage.
However, this is completely pointless from the compiler's POV, so why bother with it? As #dyp wisely said in the comments, "Why do you want foo to be standard-layout?"
You handwaved something about unions. Well, that's fine. You can write this:
union DoesntWork {
bar b; // compiler error in C++11 due to non-standard-layout type
int i;
};
union DoesWork {
foo f; // works fine in C++11, of course
int i;
};
However, equally obviously, you cannot expect this to work:
struct car {
int initialsequence;
};
struct bar {
int initialsequence;
virtual void do_bar() const {}
};
struct foo {
std::aligned_storage<sizeof(bar), alignof(bar)>::type m_storage;
bar& asBar() { return *reinterpret_cast<bar*>(&m_storage); }
};
union JustSilly {
foo f;
car c;
} js;
assert(&js.c.initialsequence == // Fails, because no matter how many
&js.f.asBar().initialsequence); // casts you add, bar still has a vptr!
In other words, you're free to lie to the compiler (via type-punning and reinterpret_cast), but that doesn't make your lies true. ;)
See also: XY problem.
Tried in OSX's XCode C++11 compiler option, and seems to work for me. Of course, you probably want to do "::new(static_cast(&f.m_storage)) bar();" in foo's constructor and invoke its destructor in foo's destructor.
When working with aligned quantities
1) It is advisable to specify alignment for the class or struct using declspec(align(16)) or __attribute((aligned(16))). I have encounter some errors when enabling optimization using VS2010, when I didn't do this.
2) I usually avoid overloading new and use the placement operator like you suggest, e.g.
#include <new> // Remember this otherwise the placement operator is not defined
SomeClass* c = (SomeClass*) _mm_malloc(sizeof(SomeClass),16);
new c SomeClass(); // This is perfectly legal
// Some work
_mm_free(c);
3) A good rules of thumb is to place aligned quantities at the start of your struct or class. This way the compiler won't do zero-padding in between members and warn about this.

Passing this as argument to members in C++

I want to pass this as argument to member variable like this:
template<class T>
struct fun
{
fun(T* pointer) : memberPointer(pointer)
{
}
T* memberPointer;
};
struct gun
{
gun() : member(this)
{
}
fun<gun> member;
};
In Visual Studio I have next warning: warning C4355: 'this' : used in base member initializer list
Can you please explain why is it wrong to do this? I just store the pointer in member constructor to use it later to call some gun functions from fun.
The potential problem is that this points to an object that has not been fully constructed. So for example if you had this:
template<class T>
struct fun
{
fun(T* pointer) : memberPointer(pointer)
{
memberPointer->callMethod(); //this is 2nd to execute
}
T* memberPointer;
};
struct gun
{
gun() : member(this) //this is 1st to execute
{
ptr = new char(); // this is 4rd to execute unless earlier UB prevents execution
}
void callMethod()
{
printf("%s", ptr); //this is 3rd to execute, you get UB here
}
fun<gun> member;
char* ptr;
};
you would run into undefined behavior because you would pass a pointer to a not fully constructed object where only a pointer to a fully constructed object should be passed. I intentionally crafted some crappy code with UB to be more convincing, in real life you won't necessarily have UB as a problem, sometimes all the objects will be in valid states so you will get some really subtle initialization order bugs.
That's not your case. Your case is fine - you don't care that the object is not yet fully constructed. However you should be careful when changing your code so that you don't get into scenario as above.
It's only a warning. If you were to deference this inside the fun constructor then you would be accessing an uninitialised object. But you aren't, you are only storing the pointer, so you can ignore the warning. If you want to turn off the warning then add this at the top of your code
#pragma warning (disable: 4355)
It is not completely wrong, but as you pass the pointer, your gun object might not be fully constructed yet. Hence, it might happen that you call methods in the base class that rely on the complete construction of your object.
What you want is to achieve static polymorphism, which is best handled through the curiously recurring template pattern (CRTP). In your case, you're almost there:
template<class Base>
struct fun : public Base
{
void foo()
{
// call gun function
Base::bar();
}
};
struct gun : public fun<gun>
{
void bar()
{
/*...*/
}
};

Using placement new to call constructor within constructor

was struggling these days.
The problem is the constructor calling.
I wrote a piece of code like:
#include <iostream>
using namespace std;
class Foo
{
private: int _n;
public:
Foo() { Foo(5);}
Foo(int n) {_n=n; cout << n << endl; }
};
int main()
{
Foo* foo = new Foo();
return 0;
}
When I constructed a Foo object outside using the default constructor:
Foo* f = new Foo();
I suppose variable _n is 5, however, it's NOT.
It's ok in Java but NOT in c++.
In addition, in Visual C++ 6 sp 6,
Foo() {this->Foo(5);}
works.
However, this expression is refused by gcc/g++ 4.
Finally, I found out the solution.
Simply changing the default constructor into
Foo() {Foo(5);}
into
Foo() { new (this) Foo(5); }
solves the problem.
What does "this" in parentheses do?
What the (this) does, is creates a brand new Foo object, at the place pointed at by this (this is called placement new). You should only use it in arrays of char and unsigned char, nowhere else (and almost never there either). Since you are constructing a Foo at the location where this has already started construction, what you are doing is undefined behavior, and would leak resources all over the place if you had base classes. Historically, the normal thing to do is merely move the initialization to a private function.
class Foo {
public:
Foo() { init(5);}
Foo(int n) {init(n);}
private:
int _n;
void init(int n) {
_n=n;
};
}
In C++11 constructors should be able to call each other with this syntax, but I don't know which compilers support it yet. According to Apache, it's supported by GCC 4.7 and Clang 3.0, but not yet Intel C++ nor VC++.
class Foo {
public:
Foo() : Foo(5) {}
Foo(int n) {_n=n;}
private:
int _n;
}
The code you started with Foo() { Foo(5);} begins construction of this, then creates a brand new Foo object on the stack with the parameter 5, then destroys it, and then considers itself completely constructed, without initializing any of it's own values. That is why it compiled and ran, but didn't appear to do anything.
In C++11 you specify this with a delegating constructor:
Foo() : Foo(5) { }
The (this) in parenthesis means that the new operator will use the address of this as the address to initalize the class.
This is very dangerous: you're in the constructor of the current object, and you invoke a new constructor on the same memory space.
Just imagine what would happen if you inherit from another class!
As for your problem, you can't call another overloaded constructor from within the constructor.
The typical solution is to have a method to initialize your class:
class Foo
{
int _n;
public:
Foo() { init(5); }
Foo( int i) { init(i); }
void init(int i) { _n = i; }
};
I had quite the same problem here: Yet another C++ Object initialization interrogation ; feel free to look at the solution.
Foo() { new (this) Foo(5); }
is a "placement new" operator that calls a constructor on a pre-allocated memory.
Now, for you other question - C++11 allows exactly that (calling constructors from one another) but the earlier standard (especially the one used by MSVC 6) doesn't have that so the use of those ugly init() methods is the way to go for you.
The correct syntax in C++ is
class Foo {
private: int _n;
public:
Foo() : Foo(5) {}
Foo(int n) _n(n) {} // As suggested by another member's edit, initializer lists are preferred
};
Alternatively, C++ allows default parameter values, such as
Foo(int n = 5);
This allows you to write one constructor rather than two.
Also, you should be sure to learn about the difference between inline and non-inline functions. This Java-style of programming is valid C++, but it has it's pros and cons along with at least one other alternative.

C++: Is it possible to call an object's function before constructor completes?

In C++, is it possible to call a function of an instance before the constructor of that instance completes?
e.g. if A's constructor instantiates B and B's constructor calls one of A's functions.
Yes, that's possible. However, you are responsible that the function invoked won't try to access any sub-objects which didn't have their constructor called. Usually this is quite error-prone, which is why it should be avoided.
This is very possible
class A;
class B {
public:
B(A* pValue);
};
class A {
public:
A() {
B value(this);
}
void SomeMethod() {}
};
B::B(A* pValue) {
pValue->SomeMethod();
}
It's possible and sometimes practically necessary (although it amplifies the ability to level a city block inadvertently). For example, in C++98, instead of defining an artificial base class for common initialization, in C++98 one often see that done by an init function called from each constructor. I'm not talking about two-phase construction, which is just Evil, but about factoring out common initialization.
C++0x provides constructor forwarding which will help to alleviate the problem.
For the in-practice it is Dangerous, one has to be extra careful about what's initialized and not. And for the purely formal there is some unnecessarily vague wording in the standard which can be construed as if the object doesn't really exist until a constructor has completed successfully. However, since that interpretation would make it UB to use e.g. an init function to factor out common initialization, which is a common practice, it can just be disregarded.
why would you wanna do that? No, It can not be done as you need to have an object as one of its parameter(s). C++ member function implementation and C function are different things.
c++ code
class foo
{
int data;
void DoSomething()
{
data++;
}
};
int main()
{
foo a; //an object
a.data = 0; //set the data member to 0
a.DoSomething(); //the object is doing something with itself and is using 'data'
}
Here is a simple way how to do it C.
typedef void (*pDoSomething) ();
typedef struct __foo
{
int data;
pDoSomething ds; //<--pointer to DoSomething function
}foo;
void DoSomething(foo* this)
{
this->data++; //<-- C++ compiler won't compile this as C++ compiler uses 'this' as one of its keywords.
}
int main()
{
foo a;
a.ds = DoSomething; // you have to set the function.
a.data = 0;
a.ds(&a); //this is the same as C++ a.DoSomething code above.
}
Finally, the answer to your question is the code below.
void DoSomething(foo* this);
int main()
{
DoSomething( ?? ); //WHAT!?? We need to pass something here.
}
See, you need an object to pass to it. The answer is no.

How do you call a constructor for global objects, for arrays of objects, and for objects inside classes/structs?

How would you call the constructor of the following class in these three situations: Global objects, arrays of objects, and objects contained in another class/struct?
The class with the constructor (used in all three examples):
class Foo {
public:
Foo(int a) { b = a; }
private:
int b;
};
And here are my attempts at calling this constructor:
Global objects
Foo global_foo(3); // works, but I can't control when the constructor is called.
int main() {
// ...
}
Arrays of objects
int main() {
// Array on stack
Foo array_of_foos[30](3); // doesn't work
// Array on heap
Foo *pointer_to_another_array = new Foo(3) [30]; // doesn't work
}
There I'm attempting to call the constructor for all elements of the arrays, but I'd also like to know how to call it on individual elements.
Objects contained in classes/structs
class Bar {
Foo foo(3); // doesn't work
};
int main() {
Bar bar;
}
Global objects
Yours is the only way. On the other hand, try to avoid this. It’s better to use functions (or even other objects) as factories instead. That way, you can control the time of creation.
Arrays of objects
There’s no way to do this directly. Non-POD objects will always be default-constructed. std::fill is often a great help. You might also want to look into allocators and std::uninitialized_fill.
Objects contained in classes/structs
Use initialization lists in your constructor:
class Bar {
Foo foo;
Bar() : foo(3) { }
};
Static members must actually be defined outside the class:
class Bar {
static Foo foo;
};
Foo Bar::foo(3);
To correct some misconceptions about globals:
The order is well defined within a compilation unit.
It is the same as the order of definition
The order across compilation units is undefined.
The order of destruction is the EXACT opposite of creation.
Not something I recommend but: So a simple solution is to to put all globals into a single compilation unit.
Alternatively you can tweak the use of function static variables.
Basically you can have a function the returns a reference to the global you want (defining the global inside the function). It will be created on first use (and destroyed in reverse order of creation).
Foo& getGlobalA() // passed parameters can be passed to constructor
{
static Foo A;
return A;
}
Foo& getGlobalB()
{
static Foo B;
return B;
}
etc.
The Konrad reply is OK, just a puntualization about the arrays....
There is a way to create an array of items(not pointers) and here it follows:
//allocate raw memory for our array
void *rawMemory = operator new[](30 * sizeof(Foo))
// point array_of_foos to this memory so we can use it as an array of Foo
Foo *array_of_foos = static_cast<Foo *>(rawMemory);
// and now we can create the array of objects(NOT pointers to the objects)
// using the buffered new operator
for (int i = 0; i < 30; i++)
new(array_of_foos[i])Foo(3);
This approach is described here: http://www.amazon.com/gp/product/0321334876?ie=UTF8&tag=aristeia.com-20&linkCode=as2&camp=1789&creative=9325&creativeASIN=0321334876
For the global case there is no way to control when it is called. The C++ spec essentially says it will be called before main() and will be destroyed sometime afterwards. Other than that' the compiler is free to do as it pleases.
In the first array case you are creating a static array of Foo objects. By default each value in the array will be initialized with the default constructor of Foo(). There is no way with a raw C++ array to force a particular overloaded constructor to be called. You can infer a bit of control by switching to a vector instead of an array. The vector constructor has an overloaded constructor vector(size,defaultValue) which should achieve what you are looking for. But in this case you must be careful because instead of calling Foo(3) it will call Foo(const Foo& other) where other is Foo(3).
The second array case is very similar to the first case. The only real difference is where the memory is allocated (on the heap instead of the stack). It has the same limitation with regards to calling to the constructor.
The contained case is a different issue. C++ has a clear separation between the definition of a field within an object and the initialization of the field. To get this to work in C++ you'll need to change your Bar definition to the following
class Bar{
Foo foo;
Bar() : foo(3){}
};
There seems to be the general gist in this thread that you cannot initialize members of an array other than using the default constructor. One answer even creates another type, just to call another constructor. Even though you can (if the array is not part as a member of a class!):
struct foo {
foo(int a): a(a) { }
explicit foo(std::string s): s(s) { }
private:
int a;
std::string s;
};
/* global */
foo f[] = { foo("global"), foo("array") };
int main() {
/* local */
foo f[] = { 10, 20, 30, foo("a"), foo("b") };
}
The type, however, needs to be copy-able: The items given are copy-initialized into the members of the array.
For arrays as members in classes, it's the best to use containers currently:
struct bar {
/* create a vector of 100 foo's, initialized with "initial" */
bar(): f(100, foo("initial")) { }
private:
std::vector<foo> f;
};
Using the placement-new technique described by andy.gurin is an option too. But note it will complicate things. You will have to call destructors yourself. And if any constructor throws, while you are still building up the array, then you need to figure where you stopped... Altogether, if you want to have arrays in your class, and want to initialize them, use of a std::vector is a simple bet.
Construction of arrays of objects:
You can modify your original example by using default parameters.
Currently only the default constructor is supported.
This is something that is being addressed by the next version (because everybody asks this question)
C++0X initializer lists solve this problem for the arrays of objects case. See this Herb Sutter blog entry, where he describes them in detail.
In the meantime you might be able to work around the problem like so:
class Foo {
public:
Foo(int a) : b(a) {}
private:
int b;
};
class Foo_3 : public Foo {
public:
Foo_3() : Foo(3) {}
};
Foo_3 array_of_foos[30];
Here, the Foo_3 class exists solely for the purpose of calling the Foo constructor with the correct argument. You could make it a template even:
template <int i>
class Foo_n : public Foo {
public:
Foo_n() : Foo(i) {}
};
Foo_n<3> array_of_foos[30];
Again this might not do exactly what you want but may provide some food for thought.
(Also note that in your Foo class you really should get into the habit of using member initializer lists instead of assignments in the constructor, as per my example above)
I reckon there are two ways to make sure global class objects' constructors are called safely at the time of their "creation":
Declare them in a namespace and make that namespace globally accessible.
Make it a global pointer to the class object and assign a new class object to it in main(), granted code for other global objects' constructors that access the object will execute before this.
Just my two cents.