When calling this vector constructor:
vector( size_type count,
const T& value,
const Allocator& alloc = Allocator());
If exception will be thrown and some T objects will be already constructed but not all of them, will constructed elements always gets destructor called?
std::vector<std::vector<T>> internalBuffer =
std::vector<std::vector<T>>(1024, std::vector<T>(1024, 0));
I'm assuming default allocator and c++11.
Note: that particular constructor was removed from C++11.
Other than that, you are correct that the destructors of all the already constructed objects will be called in this case.
Related
I found a compiler error that I can not understand why it happens only for std::map with std::unique_ptr.
Assume we have the follow unoredered map object and an iteration code for it:
std::unordered_map<uint32_t, std::shared_ptr<char>> map;
for (const std::pair<uint32_t, std::shared_ptr<char>>& item : map)
{
// do something
}
That's compiled well, but if we use unique pointer instead the shared pointer as follows, then we get a compiler error about the iteration pair type:
std::unordered_map<uint32_t, std::unique_ptr<char>> map;
for (const std::pair<uint32_t, std::unique_ptr<char>>& item : map)
{
// do something
}
error C2440: 'initializing': cannot convert from 'std::pair<const _Kty,_Ty>' to
'const std::pair<uint32_t,std::unique_ptr<char,std::default_delete<_Ty>>>
Following this error, we can just add 'const' to the key type and it is compiled.
for (const std::pair<const uint32_t, std::unique_ptr<char>>& item : map)
^^^
|||
Why is this compiling error happens just for unique pointer?
A friend gave me the answer and I'm sharing.
The answer lies in the concept of implicit conversion(copy) a compiler is allowed to do.
Lets see the follow simple example:
const char x = 4;
const char& r = x; // r is reference for x. Checking their addresses yields the same
// address.
const int& ir = c; // implicit creation of object + conversion(copy).
// ir is different type of x, therefor compiler does implicit
// conversion(copy): it creates behind the scene an object of int,
// convert x into this temporary object. The temporary int object is
// then bound to the reference ir. Checking addresses of ir and x
// yields different addresses because ir is reference of the temporary
// object, not to x
So even we use reference - planning for just pointing on an existing object,
we may actually have an object construction + copy (if the types are different and there is conversion between them).
The same happens in the loop I gave in the question:
std::unordered_map<uint32_t, std::shared_ptr<char>> map;
for (const std::pair<uint32_t, std::shared_ptr<char>>& item : map)
{
// do something
}
while the real object held by the map is of type of
std::pair<const uint32_t, std::shared_ptr<char>>
the loop uses reference of different type:
std::pair<uint32_t, std::shared_ptr<char>>
and therefor, behind the scene, for every iteration, a new temporary object is implicitly constructed and a copy operation for conversion is done.
Not only that it isn't efficient, but it also failed to be compiled when the value is unique_ptr because the conversion does copy and unique_ptr can not be copied.
Thats why using 'auto' may save you such mistakes,
std::unordered_map<uint32_t, std::shared_ptr<char>> map;
for (const auto& item : map)
{
// do something
}
I myself sometimes prefer to play and use the explicit form instead 'auto' in order to face such problems and learn :)
I am working with shared_ptr storing pointers of a C library.
Here an example of such a C library containing the header bar.h:
#pragma once
typedef struct Flupp MyFlupp;
MyFlupp *
create_flupp();
void
del_flupp(MyFlupp * fp);
void
print_flupp(MyFlupp * f);
Here the struct has a forward declaration and is defined in the bar.so.
I am using the bar.so in my C++ code:
#include <memory>
extern "C"{
#include "bar.h"
}
int main()
{
std::shared_ptr<MyFlupp> flupp_ptr(nullptr, del_flupp);
flupp_ptr.reset(create_flupp());
print_flupp(flupp_ptr.get());
return 0;
}
Here I am storing the MyFlupp* in a shared_ptr. On the declaration, MyFlupp* is unknown and set to nullptr. Later I am calling the reset operation to set the valid pointer. But when I am compling the code, I get the following error:
In file included from /usr/include/c++/8/bits/shared_ptr.h:52,
from /usr/include/c++/8/memory:81,
from test_foo.cpp:1:
/usr/include/c++/8/bits/shared_ptr_base.h: In instantiation of ‘std::__shared_ptr<_Tp, _Lp>::__shared_ptr(_Yp*) [with _Yp = Flupp; <template-parameter-2-2> = void; _Tp = Flupp; __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2]’:
/usr/include/c++/8/bits/shared_ptr_base.h:1293:4: required from ‘std::__shared_ptr<_Tp, _Lp>::_SafeConv<_Yp> std::__shared_ptr<_Tp, _Lp>::reset(_Yp*) [with _Yp = Flupp; _Tp = Flupp; __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2; std::__shared_ptr<_Tp, _Lp>::_SafeConv<_Yp> = void]’
test_foo.cpp:10:35: required from here
/usr/include/c++/8/bits/shared_ptr_base.h:1126:19: error: invalid application of ‘sizeof’ to incomplete type ‘Flupp’
static_assert( sizeof(_Yp) > 0, "incomplete type" );
When I am providing the deleter to the reset operation than it is working.
flupp_ptr.reset(create_flupp(), del_flupp);
Can anybody explain me whats going on? I already looked #cppreference but I does not found an answer.
The problem is that the type Flupp has only been forward-declared, but not defined. In the context of the use here, it is considered an incomplete type.
This has certain implications for the use with std::shared_ptr:
std::shared_ptr may be used with an incomplete type T. However, the
constructor from a raw pointer (template<class Y> shared_ptr(Y*)) and
the template<class Y> void reset(Y*) member function may only be
called with a pointer to a complete type (note that std::unique_ptr
may be constructed from a raw pointer to an incomplete type).
Source: cppreference.com
Instead you need to use the respective overloads that accept a pointer and the deleter as arguments.
With unique_ptr this is not necessary, as that one stores the custom deleter as part of the type. But with shared_ptr the deleter is type-erased and only recovered at runtime. This allows you to change the deleter of an existing shared_ptr when calling reset. For this reason you always need to re-state which deleter to use whenever you're calling reset. If no deleter is given, each call to reset will also implicitly reset the deleter to just calling delete on the managed pointer.
So to make it work, just change your reset call to
flupp_ptr.reset(create_flupp(), del_flupp);
class A { public: int x[100]; };
Declaring A a will not initialize the object (to be seen by garbage values in the field x).
The following will trigger initialization: A a{} or auto a = A() or auto a = A{}.
Should any particular one of the three be preferred?
Next, let us make it a member of another class:
class B { public: A a; };
The default constructor of B appears to take care of initialization of a.
However, if using a custom constructor, I have to take care of it.
The following two options work:
class B { public: A a; B() : a() { } };
or:
class B { public: A a{}; B() { } };
Should any particular one of the two be preferred?
Initialization
class A { public: int x[100]; };
Declaring A a will not initialize the object (to be seen by garbage
values in the field x).
Correct A a is defined without an initializer and does not fulfill any of the requirements for default initialization.
1) The following will trigger initialization:
A a{};
Yes;
a{} performs list initialization which
becomes value initialization if {} is empty, or could be aggregate initialization if A is an aggregate.
Works even if the default constructor is deleted. e.g. A() = delete; (If 'A' is still considered an aggregate)
Will warn of narrowing conversion.
2) The following will trigger initialization:
auto a = A();
Yes;
This is copy initialization where a prvalue temporary is constructed with direct initialization () which
uses value initialization if the () is empty.
No hope of aggregate initialization.
The prvalue temporary is then used to direct-initialize the object.
Copy elision may be, and normally is employed, to optimize out the copy and construct A in place.
Side effects of skipping copy/move constructors are allowed.
Move constructor may not be deleted. e.g A(A&&) = delete;
If copy constructor is deleted then move constructor must be present. e.g. A(const A&) = delete; A(A&&) = default;
Will not warn of narrowing conversion.
3) The following will trigger initialization:
auto a = A{}
Yes;
This is copy initialization where a prvalue temporary is constructed with list initialization {} which
uses value initialization if {} is empty, or could be aggregate initialization if A is an aggregate.
The prvalue temporary is then used to direct-initialize the object.
Copy elision may be, and normally is employed, to optimize out the copy and construct A in place.
Side effects of skipping copy/move constructors are allowed.
Move constructor may not be deleted. e.g A(A&&) = delete;
If copy constructor is deleted then move constructor must be present. e.g. A(const A&) = delete; A(A&&) = default;
Will warn of narrowing conversion.
Works even if the default constructor is deleted. e.g. A() = delete; (If 'A' is still considered an aggregate)
Should any particular one of the three be preferred?
Clearly you should prefer A a{}.
Member Initialization
Next, let us make it a member of another class:
class B { public: A a; };
The default constructor of B appears to take care of initialization
of a.
No this is not correct.
the implicitly-defined default constructor of 'B' will call the default constructor of A, but will not initialize the members. No direct or list initialization will be triggered. Statement B b; for this example will call the default constructor, but leaves indeterminate values of A's array.
1) However, if using a custom constructor, I have to take care of it. The
following two options work:
class B { public: A a; B() : a() { } };
This will work;
: a() is a constructor initializer and a() is a member initializer as part of the member initializer list.
Uses direct initialization () or, if () is empty, value initialization.
No hope of using aggregate initialization.
Will not warn of narrowing conversion.
2) or:
class B { public: A a{}; B() { } };
This will work;
a now has a non-static data member initializer, which may require a constructor to initialize it if you are using aggregate initialization and the compiler is not fully C++14 compliant.
The member initializer uses list initialization {} which
may become either value initialization if {} is empty or aggregate initialization if A is an aggregate.
If a is the only member then the default constructor does not have to be defined and the default constructor will be implicitly defined.
Clearly you should prefer the second option.
Personally, I prefer using braces everywhere, with some exceptions for auto and cases where a constructor could mistake it for std::initializer_list:
class B { public: A a{}; };
A std::vector constructor will behave differently for std::vector<int> v1(5,10) and std::vector<int> v1{5,10}. with (5,10) you get 5 elements with the value 10 in each one, but with {5,10} you get two elements containing 5 and 10 respectively because std::initializer_list is strongly preferred if you use braces. This is explained very nicely in item 7 of Effective Modern C++ by Scott Meyers.
Specifically for member initializer lists, two formats may be considered:
Direct initialization a() which becomes value initialization if the () is empty.
List initialization a{} which also becomes value initialization if {} is empty.
In member initializer lists, fortunately, there is no risk of the most vexing parse. Outside of the initializer list, as a statement on its own, A a() would have declared a function vs. A a{} which would have been clear. Also, list initialization has the benefit of preventing narrowing conversions.
So, in summary the answer to this question is that it depends on what you want to be sure of and that will determine the form you select. For empty initializers the rules are more forgiving.
"Theory" question if you will.
In order to execute/make use of the move constructor in a class, do I always have to use std::move(...) to tell the compiler that I wish to 'move' an object rather than copy it?
Are there any cases where the compiler will invoke the move constructor for me without the use of std::move? (My guess would be in function return values?)
According to cppreference.com (http://en.cppreference.com/w/cpp/language/move_constructor):
The move constructor is called whenever an object is initialized from xvalue of the same type, which includes
initialization, T a = std::move(b); or T a(std::move(b));, where b is of type T;
function argument passing: f(std::move(a));, where a is of type T and f is void f(T t);
function return: return a; inside a function such as T f(), where a is of type T which has a move constructor.
In most cases, yes std::move is needed.
The compiler will invoke the move constructor without std::move when:
returning a local variable by value
when constructing an object from an rvalue of the same type
In all other cases, use std::move. E.g.:
struct S {
std::string name;
S(std::string name) : name(std::move(name)) {}
};
and
std::unique_ptr<Base> func() {
auto p = std::make_unique<Derived>();
return std::move(p); // doesn't work without std::move
}
std::move is just a cast.
unique_ptr<int> global;
auto v = unique_ptr<int>(global); // global is a lvalue, therefore the
unique_ptr(unique_ptr<T>&v) constructor that accepts lvalue references is called.
auto v = unique_ptr<int>(std::move(global)); // move returns a &&rvalue reference, therefore the
unique_ptr(unique_ptr<T>&&v) constructor that accepts &&rvalue references is used.
When the criteria for elision of a copy operation are met and the object to be copied is designated by an lvalue, overload resolution to select the constructor for the copy is first performed as if the object were designated by an rvalue.
therefore,
unique_ptr<int> hello()
{
unique_ptr<int> local;
return local;
// local is an lvalue, but since the critera for elision is met,
// the returned object is created using local as if it was an rvalue
}
Also,
unique_ptr<int> hello = std::unique_ptr<int>();
// we have a pure rvalue in the right, therefore no std::move() cast is needed.
I'm looking for a way of checking whether a std::function pointer is bound to a member function of a particular object. I'm aware that std::function itself has no '==' operator. I have however come across the std::function::target method which should be able, in principle, to give me the address of the function to which the pointer is pointing. My starting point was therefore this:
bool MyClass::isThePointerSetToMyMethod(std::function<void (const char*, string)> const& candidate)
{
// Create a pointer to the local reportFileError function using the same syntax that we did in the constructor:
std::function<void (const char *, string)> localFn = std::bind(&MyClass::theLocalMember, this,
std::placeholders::_1, std::placeholders::_2);
// Find the target
auto ptr1 = localFn.target< std::function<void (const char *, string)> >();
// Find the target of the candidate
auto ptr2 = candidate.target< std::function<void (const char *, string)> >();
// Compare the two pointers to see whether they actually point to the same function:
if (!ptr1 || !ptr2) return false;
if (*ptr1 == *ptr2)
return true;
else
return false;
}
This doesn't work, and the reason is that the values of 'ptr1' and 'ptr2' are always returned as null. According to the documentation for the std::function::target method, this must be because the type that I've specified for the target is not correct.
If I look at what target_type(localFn) actually is (using Visual C++ 2013), it's a bit frightening:
class std::_Bind<1,void,struct std::_Pmf_wrap<void (__thiscall MyClass::*)(char const *, string),void,class MyClass,char const *,string>,class MyClass * const,class std::_Ph<1> &,class std::_Ph<2> &>
Nevertheless, target_type(candidate) gives the same result, so I thought I'd try a typedef:
bool MyClass::isThePointerSetToMyMethod(std::function<void (const char*, string)> const& candidate)
{
typedef class std::_Bind<1,void,struct std::_Pmf_wrap<void (__thiscall MyClass::*)(char const *, string),void,class MyClass,char const *,string>,class MyClass * const,class std::_Ph<1> &,class std::_Ph<2> &> wally;
// Create a pointer to the local reportFileError function using the same syntax that we did in the constructor:
std::function<void (const char *, string)> localFn = std::bind(&MyClass::theLocalMember, this,
std::placeholders::_1, std::placeholders::_2);
// Find the target
auto ptr1 = localFn.target< wally >();
// Find the target of the candidate
auto ptr2 = candidate.target< wally >();
// Compare the two pointers to see whether they actually point to the same function:
if (!ptr1 || !ptr2) return false;
if (*ptr1 == *ptr2)
return true;
else
return false;
}
Alas this gets me no further; the values of ptr1 and ptr2 are still null.
So for now I've run out of ideas. Is there anyone reading this who knows either:
(1) The appropriate form for a typedef for a std::function pointer to the member function of a class, or
(2) A better way to achieve my ultimate objective, which is to tell whether a std::function pointer is pointing to a particular object's member function or whether it isn't?
[Background, in case anyone is interested: the reason I'm doing this is that I have a callback table where different callbacks are set to different functions depending on the state that the system is in; this makes state control very simple, as it means that in a given context I can call a given callback and know that the actions taken by the function I've called will be appropriate for the current state, without having to know anything about what that state actually is. Usually, when an object is instantiated which will change the system state, it takes control of the relevant callback(s) and binds them to whatever local member functions are appropriate for whatever state it's in. Under these circumstances, however, the object's destructor ought to return the callbacks to their status quo ante so that they are not left pointing to nothing.
Very rarely, an object may bind the callbacks to its member functions in its constructor, but before its destructor is called another object may take control of the same callbacks itself, and re-bind them to member functions of its own. If this happens, then the first object's destructor needs to be able to recognise that this has happened, and exit without affecting the callbacks' assignment to the second object's methods. The obvious way to do this is for the destructor to be able to check whether the callbacks are still assigned to its own methods or not, and if they are not then to leave well alone.]
Flesh out the callback table into a class which manages the table. All modifications to the table should be done through this class's interface. Internally, you would maintain a stack-like structure which lets you undo the changes done to the callback table. Barebones interface would look something like:
class CallbackTable
{
public:
bool ApplyChanges(...)
{
//Push the old values of the entries that would be changed here into your change-tracker stack and modify the table
}
bool UnApplyChanges(...)
{
//Pop the change-tracker stack and restore the table to the state it was in before the most recent change was applied.
}
};