Copy list initialization - c++11

I am learning C++, but there is a problem about copy initialization which really confuses me. The following is the class that I created.
class Example{
public:
Example(initializer_list<int> il) {cout<<"constructor"<<endl;}
Example(const char *) {cout<<"constructor"<<endl;}
Example(const Example &) {cout<<"copy constructor"<<endl;}
};
Constructor and copy constructor will be called if the code looks like this, Example ex = "Hello world". However, if the code is Example ex = {0,1,2,3}, only constructor will be called, not copy constructor. Any explains? I'd really appreciate.

Related

Static casting to unique_ptr

I have a head file which needs to hide some internals for complexity and "secrecy" reasons. I've therefore a raw void pointer declared in the oublic header, inside the code there are static casts to convert the raw pointer to it's actual type.
Now due to general memory management changes I need to change the type internally to a unique_ptr (it's coming from an object factory now as a unique_ptr, previously it was a raw pointer).
So in my header I have this:
class SomeClass {
private:
void *_hiddenTypeInstance;
}
Is it possible to static-cast this _hiddenTypeInstance to an internally known unique_ptr type?
This is not a direct answer of what you wanted, but a proposal how to do things nicer:) You can actually still use the memory semantics of std::unique_ptr with hiding the internals and without using the ugly void*. As others have mentioned, you should look into PIMPL, but to summarize:
Forward declare the internal type in the public header
Use std::unique_ptr with that type and provide a dtor for the class which holds that member (otherwise you will get compilation errors because a default dtor will be generated, that will try to delete the forward declared class and will fail to do so).
This would look something like this:
#include <memory>
class CPrivate; // Forward declare the internal class
class CPublic
{
public:
// You need the dtor here, since when you implement it in the .cpp of your library,
// where the definition of CPrivate is known, the dtor of std::unique_ptr will know how to delete it.
// If you do not put the dtor here, a default one will be generated here which invokes the dtor of std::unique_ptr, and here
// since CPrivate is forward declared the dtor of std::unique_ptr will not know how to delete it and you will get an error
~CPublic();
private:
std::unique_ptr<CPrivate> m_pPrivate;
}
By using this, you can then escape the casts inside the implementation from the void* to the actual type.
As for the original question - you can always cast void* to a std::unique_ptr<T>* (a pointer to a unique_ptr). But I would advise to evaluate the solution above. Because the void* thing moves away all type strictness - e.g what happens if someone changes T ?
if i understand you problem in a correct way: here is what you can do. This example is just for understanding of a concept. You can use it in your own code. Since I dont have the entire code I cant write exact solution.
class SomeClass {
private:
void *_hiddenTypeInstance;
public:
std::unique_ptr<int> foo() {
int a;
a = 2;
return std::unique_ptr<int>(&a);
}
void bar() {
std::unique_ptr<int> temp_hidden_type_instance;
temp_hidden_type_instance = std::unique_ptr<int>(static_cast<int*>(_hiddenTypeInstance));
temp_hidden_type_instance = foo();
}
};

c++11 local static member variable destruction order for shared_ptr objects

I've been struggling with a destructor call order which I cannot really understand.
Say we have the following definitions:
#include <memory>
#include <iostream>
class DummyClass {
std::string name;
public:
DummyClass(std::string name) : name(name) { std::cout << "DummyClass(" << name << ")" << std::endl; }
~DummyClass() { std::cout << "~DummyClass(" << name << ")" << std::endl; }
};
class TestClass {
private:
static DummyClass dummy;
static DummyClass& objects() {
static DummyClass dummy("inner");
return dummy;
}
public:
TestClass() {
std::cout << "TestClass" << std::endl;
std::cout << "TestClass Objects is: " << &objects() << std::endl;
}
virtual ~TestClass() {
std::cout << "~TestClass Objects is: " << &objects() << std::endl;
std::cout << "~TestClass" << std::endl;
}
};
DummyClass TestClass::dummy("outer");
Now, If I instantiate the TestClass as follows:
TestClass *mTest = nullptr;
int main() {
mTest = new TestClass(); delete mTest;
return 0;
}
The output obtained is the one I would expect:
DummyClass(outer)
TestClass
DummyClass(inner)
TestClass Objects is: 0x....
~TestClass Objects is: 0x....
~TestClass
~DummyClass(inner)
~DummyClass(outer)
But, now, if I use a shared_ptr for mTest, like:
std::shared_ptr<TestClass> mTest;
int main() {
mTest = std::make_shared<TestClass>();
return 0;
}
the output produced is:
DummyClass(outer)
TestClass
DummyClass(inner)
TestClass Objects is: 0x....
~DummyClass(inner)
~TestClass Objects is: 0x....
~TestClass
~DummyClass(outer)
Can someone explain why is the DummyClass inner object being destroyed before the end of the TestClass object destructor, in this particular case?
I found consistent behavior for gcc 5.2.0 using -std=gnu++11 and clang 3.8.0 with -std=c++11 but could not find any particular documentation citing this example.
Edit: To clarify: all of the code above was written in the same translation unit (*.cpp file) in the presented order. It is a simplification of a usage case where I have a header only class definition which must hold a static list of this pointers to derived class objects. These pointers are added via ctor and removed when the dtor is reached. The problem is triggered when destroying the last object. The list is kept inside a static method and accessed through it to achieve the header only goal.
The rules for all objects with static storage duration (namespace members, static class members, and static objects in function definitions) are:
If the entire initialization can be considered a constant expression, that initialization happens before anything else. (Doesn't apply to anything in your examples.) Otherwise,
Namespace members and static class members are guaranteed to begin initialization at some point before any function in the same translation unit is called. (In most implementations, if we ignore dynamic library loading, all of these happen before main begins. In your examples, since main is in the same TU, we know they happen before main.)
Namespace members and static class members defined in the same TU begin their initializations in the order of their definitions.
For namespace members and static class members defined in different TUs, there is no guarantee on order of initialization!
Static objects defined inside a function begin their initialization the first time program control reaches the definition (if ever).
When main returns or std::exit is called, all objects with static storage duration are destroyed in order opposite to when each completed its initialization.
So in your second example:
Initialization of TestClass::dummy begins. First a temporary std::string is created, and then DummyClass::DummyClass(std::string) is called.
The DummyClass constructor does a std::string copy, then outputs "DummyClass(outer)\n". The temporary std::string is destroyed. Initialization of TestClass::dummy is complete.
Initialization of ::mTest begins. This calls std::shared_ptr<TestClass>::shared_ptr().
The shared_ptr constructor sets up the smart pointer to be null. Initialization of ::mTest is complete.
main begins.
The std::make_shared call ends up creating a TestClass object, calling TestClass::TestClass(). This constructor first prints "TestClass\n", then calls TestClass::objects().
Inside TestClass::objects(), initialization of local object dummy begins. Again a temporary std::string is created, and DummyClass::DummyClass(std::string) is called.
The DummyClass constructor does a std::string copy, then outputs "DummyClass(inner)\n". The temporary std::string is destroyed. Initialization of objects' dummy is complete.
TestClass::TestClass() continues, printing "TestClass Objects is: 0x...\n". Initialization of the dynamic TestClass object is complete.
Back in main, the make_shared function returns a temporary std::shared_ptr<TestClass>. A move assignment moves from the returned temporary to ::mTest, then the temporary is destroyed. Note that although the TestClass object is associated with ::mTest, it has dynamic storage duration, not static storage duration, so the above rules do not apply to it.
main returns. C++ begins destroying objects with static storage duration.
The last static object to finish initialization was the dummy local of TestClass::objects() at step 8 above, so it is destroyed first. Its destructor body outputs "~DummyClass(inner)\n".
The next object to finish initializing was ::mTest in step 4 above, so its destruction begins next. The ~shared_ptr destructor ends up destroying the owned dynamic TestClass object.
The TestClass::~TestClass() destructor body first calls TestClass::objects().
In TestClass::objects(), we encounter the definition of an already destroyed function-local static, which is Undefined Behavior! Apparently though, your implementation does nothing but return a reference to the storage that formerly contained dummy, and it's probably a good thing you didn't do anything with it other than take the address.
TestClass::~TestClass() continues, outputting "~TestClass Objects is: 0x...\n" and then "~TestClass\n".
The ~shared_ptr destructor for ::mTest deallocates associated memory and completes.
Finally, the first static object to finish initialization was TestClass::dummy, in step 2 above, so it is destroyed last. The DummyClass::~DummyClass destructor body outputs "~DummyClass\n". The program is finished.
So the big difference between your two examples is the fact that the TestClass destruction gets delayed until the shared_ptr is destroyed - it doesn't really matter when in the scheme of things the TestClass was created. Since the shared_ptr was created before the "inner" DummyClass in the second example, its destruction happens after the "inner" object is gone, causing that Undefined Behavior.
If this is a simplification of an actual issue you ran into and need to fix, you might try adding something like
class TestClass {
// ...
public:
class ForceInit {
ForceInit() { TestClass::objects(); }
};
// ...
};
// ...
TestClass::ForceInit force_init_before_mTest;
std::shared_ptr<TestClass> mTest;
It's not related to shared_ptr but to the order of destruction of global variables in modules (cc files). The spec states that the order is undefined so you can not assume that static inner object will be destroyed after or before another global object. If you need to have a consistent order of destruction I advise that you take care of it explicitly.

initialize a string size during declaration

suppose I have a class like this and I would like to create a string with a
specific capacity. I tried doing the following but that did not work.
Any suggestions ? I know I could do it in the constructor but would like to do it during the declaration if possible.
class foo
{
std::string bar = std::string().resize(45);
}
I get the error
main.cpp: In function 'int main()':
main.cpp:8:46: error: conversion from 'void' to non-scalar type 'std::__cxx11::string {aka std::__cxx11::basic_string}' requested
std::string test = std::string().resize(45);
In C++, you probably don't want to "chain" methods unless previous methods have the correct return type.
As suggested by #James Maa, you can do simply use the constructor.
In c++11 we have new feature called move constructor so
string str = string();
doesn't cause extra time.
http://en.cppreference.com/w/cpp/language/move_constructor
with move constructor, the program would directly use the address of the temporary constructed string after = sign, without making a copy.
The problem is that resize()function in c++ actually returns void
basic_string( size_type count,
CharT ch,
const Allocator& alloc = Allocator() );
This constructor might be something you are directly interested in.
You can do something with
std::string str(45, ' ');

C++11 Initializing a std::string member

When I initialize the std::string member of a class calling its C string constructor, I receive the following errors:
error: expected identifier before string constant
error: expected ',' or '...' before string constant
Although, the program compiles successfully when I use copy initialization or list initialization.
class Element
{
private:
std::string sName_("RandomName"); // Compile error
std::string sName_ = "RandomName"; // OK
std::string sName_{"RandomName"}; // OK
}
What seems to be the problem?
UPDATE
Now I realize this is a stupid question, because, as #p512 says, the compiler will see it as a erroneous method declaration. But I think this question should remain for other people that will do the same thinking error.
std::string sName_("RandomName");
This is an erroneous function declaration - at least that's what the compiler makes of it. Instead you can use something like this:
std::string sName_ = std::string("RandomName");
You can also use initializer lists in the constructor of your class:
class A {
public:
A() : sName_("RandomName") {}
std::string sName_;
};
You can find more on that here: http://en.cppreference.com/w/cpp/language/initializer_list

C++11 implicit copy constructor while implementing explicitly a constructor

I ran into a problem. I implemented a constructor for a class, but why are implicitly generated the other constructors, like the copy one?
I thought, that if I define a constructor explicitly, then the compiler doesn't generates implicitly other ones. I'm really hoping, that this a VC++ specific thing, and that this code doesn't conforms to ISO:IEC C++11:
class Foo
{
int bar;
public:
Foo(int&& arg) : bar(arg) { cout << "RConstruction" << endl; }
};
int main(int, const char*[])
{
Foo f = Foo(42);
/* Create unused temporary on the stack */
Foo::Foo(f); /* calling Foo::Foo(const Foo&): this shouldn't work... */
return (0);
}
Please keep in mind, that this is a sample code, created exactly for this situation, for demonstration purposes, I expect answers only that strictly relate to this question.
That's not a move constructor, so it doesn't suppress any implicit ones.
Just like Foo(const int&) isn't a copy constructor, Foo(int&&) isn't a move constructor, it's just a constructor taking an rvalue reference.
A move constructor looks like one of:
Foo(Foo&&)
Foo(const Foo&&)
Foo(volatile Foo&&)
Foo(const volatile Foo&&)
I thought, that if I define a constructor explicitly, then the compiler doesn't generates implicitly other ones.
If you define any constructor the compiler doesn't generate the default constructor, but it still generates the others. Define the as deleted if you don't want them:
Foo(const Foo&) = delete;
Foo& operator=(const Foo&) = delete;
You did not declare a move constructor, but a regular constructor : no implicit constructor will be deleted.
A move constructor would be of the form Foo(Foo&& arg) (with any cv-qualifier on the argument)
Also note that this statement is not valid C++ :
Foo::Foo(f);
Maybe you meant :
Foo g = Foo(f);

Resources