Using unique_ptr<CBitmap> with VS2017 [duplicate] - unique-ptr

I have a C++ object of type ObjectArray
typedef map<int64_t, std::unique_ptr<Class1>> ObjectArray;
What is the syntax to create a unique_ptr to a new object of type Class1 and insert it into an object of type ObjectArray?

As a first remark, I wouldn't call it ObjectArray if it is a map and not an array.
Anyway, you can insert objects this way:
ObjectArray myMap;
myMap.insert(std::make_pair(0, std::unique_ptr<Class1>(new Class1())));
Or this way:
ObjectArray myMap;
myMap[0] = std::unique_ptr<Class1>(new Class1());
The difference between the two forms is that the former will fail if the key 0 is already present in the map, while the second one will overwrite its value with the new one.
In C++14, you may want to use std::make_unique() instead of constructing the unique_ptr from a new expression. For instance:
myMap[0] = std::make_unique<Class1>();

If you want to add an existing pointer to insert into the map, you will have to use std::move.
For example:
std::unique_ptr<Class1> classPtr(new Class1);
myMap.insert(std::make_pair(0,std::move(classPtr)));
or similar:
myMap[0] = std::move(classPtr);
if one wants insert a new or overwrite an already resisting key.

In addition to previous answers, I wanted to point out that there is also a method emplace (it's convenient when you cannot/don't want to make a copy), so you can write it like this:
ObjectArray object_array;
auto pointer = std::make_unique<Class1>(...); // since C++14
object_array.emplace(239LL, std::move(pointer));
// You can also inline unique pointer:
object_array.emplace(30LL, std::make_unique<Class1>(...));

Related

How to insert into a repeatedptrfiled just like vector.insert(iterator)

std::vector has a function to insert, which is
iterator insert(const_iterator _Where, const _Ty& _Val) { // insert _Val at _Where
return emplace(_Where, _Val);
}
is there any similar interface in repeatedptrfiled or some other way to insert into a repeatedptrfield by iterator but not index.
If you look at the docs here, there is nothing that allows you to set a value using an iterator. The closest thing is Set(int index, const Element& value) which is rather unfortunate. If you want to use a range based for loop but need Python-like element enumeration, consider using enumerate from CPPItertools.
Hy, the repeated field from protobuf is a std::vector and you can use the insert from it. Not very elegantly but it should work.

Iterating over const_iterator

ALL,
I have a function with the following signature:
void foo(const std::vector<Bar *> &myvec);
Inside this function I need to loop thru the members of the vector and perform some operations.
So, I tried this:
for( std::vector<Bar *>::const_iterator it = myvec.begin(); it < myvec.end(); ++it )
{
// modify properties of Bar * pointer
(*it)->SetSomeValue( baz );
}
however this code asserts since the iterator is constant.
Now obviously the vector is constant, which means that the function shouldn't be modifying myvec.
What's the best solution here?
Can I use const_cast here to remove constness? It would be kind of hack-ish, but if it works.
But I feel there must be a better solution.
TIA!!
You should use the myvec.cbegin() method instead of myvec.begin(), to ensure that you are not modifying the object the iterator points to.
Of course, for myvec.end(), use myvec.cend() accordingly.
The iterator itself doesn't need to be a const_iterator, in the contrary, you want to modify the objects it gives you - set_...() sounds like a non-const activity.

How to use make_shared to create an array of objects of the same type?

We could use "make_shared" to create an object faster and safer compared to use "new". For example,
shared_ptr<Dog> p = make_shared<Dog>("Luther").
If I need to create an array of objects (e.g. Dog[3]), is it possible to use "make_shared" instead "new"? Besides, is it possible to use a customized delete function with make_shared method?
auto parr = make_shared<std::array<Dog, 3>>(std::array<Dog, 3>{"Bob", "Charlie", "Alice"});
If you want a shared pointer to the nth element...
auto pelem = std::shared_ptr<Dog*>{p, p->data()+n};
which does 0 allocations.

Casting to rvalue reference to "force" a move in a return value - clarification

Ok, I am starting to get the jist of rvalue references (I think). I have this code snippet that I was writing:
#include <iostream>
using namespace std;
std::string get_string()
{
std::string str{"here is your string\n"};
return std::move(str); // <----- cast here?
}
int main ()
{
std::string my_string = std::move(get_string()); // <----- or cast here?
std::cout << my_string;
return 0;
}
So I have a simple example where I have a function that returns a copy of a string. I have read that its bad (and got the core-dumps to prove it!) to return any reference to a local temp variable so I have discounted trying that.
In the assignment in main() I don't want to copy-construct that string I want to move-construct/assign the string to avoid copying the string too much.
Q1: I return a "copy" of the temp var in get_string() - but I have cast the return value to rvalue-red. Is that pointless or is that doing anything useful?
Q2: Assuming Q1's answer is I don't need to do that. Then am I moving the fresh copy of the temp variable into my_string, or am I moving directly the temp variable str into my_string.
Q3: what is the minimum number of copies that you need in order to get a string return value stored into an "external" (in my case in main()) variable, and how do you do that (if I am not already achieving it)?
I return a "copy" of the temp var in get_string() - but I have cast the return value to rvalue-red. Is that pointless or is that doing anything useful?
You don't have to use std::move in that situation, as local variables returned by value are "implicitly moved" for you. There's a special rule in the Standard for this. In this case, your move is pessimizing as it can prevent RVO (clang warns on this).
Q2: Assuming Q1's answer is I don't need to do that. Then am I moving the fresh copy of the temp variable into my_string, or am I moving directly the temp variable str into my_string.
You don't need to std::move the result of calling get_string(). get_string() is a prvalue, which means that the move constructor of my_string will automatically be called (pre-C++17). In C++17 and above, mandatory copy elision will ensure that no moves/copies happen (with prvalues).
Q3: what is the minimum number of copies that you need in order to get a string return value stored into an "external" (in my case in main()) variable, and how do you do that (if I am not already achieving it)?
Depends on the Standard and on whether or not RVO takes place. If RVO takes place, you will have 0 copies and 0 moves. If you're targeting C++17 and initializing from a prvalue, you are guaranteed to have 0 copies and 0 moves. If neither take place, you'll probably have a single move - I don't see why any copy should occur here.
You do not need to use std::move on the return value which is a local variable. The compiler does that for you:
If expression is an lvalue expression that is the (possibly parenthesized) name of an automatic storage duration object declared in the body or as a parameter of the innermost enclosing function or lambda expression, then overload resolution to select the constructor to use for initialization of the returned value is performed twice: first as if expression were an rvalue expression (thus it may select the move constructor), and if no suitable conversion is available, or if the type of the first parameter of the selected constructor is not an rvalue reference to the object's type (possibly cv-qualified), overload resolution is performed a second time, with expression considered as an lvalue (so it may select the copy constructor taking a reference to non-const).

Question about a terminology which implements something like this list.Add(new{a=1, b=2})

What is the terminology for the usage of "new" in:
list.Add(new{a=1, b=2})
And what type should I replace the T in List getList if I want to use the list as the returned value? I don't want to replace T with "object" because I want to parse it in Linq query.
Thanks.
Since you did not specify a type: new {1), it's called object initializers with anonymous types. (MSDN Explaining them) The Object Initializer part is where you do { a=1, b=2}.
If you want to be able to reference a type, you will have to create a type and stuff the values in.
list.Add(
new MyType() {
a=1,
b=2
});
If you are just going to be pairing two items look into using the Pair Class. There is also a Triplet Class just in case you might want to store 3 items.

Resources