I was wondering if the following is correct usage of a std::shared_ptr.
All I want to do with the originally created pointer is add it onto the vector on class A,
which will be later on retrieved
class A
{
public:
void AddToVec(std::shared_ptr<B> b)
{
myVec_.push_back(b);
}
std::vector<std::shared_ptr<B>> GetVec()
{
return myVec_;
}
private:
std::vector<std::shared_ptr<B>> myVec_;
}
Then on main, a pointer is created and passed with the following way
int main()
{
A a;
std::shared_ptr<B> ptr = std::make_shared<B>();
a.AddToVec(std::move(ptr));
}
Is the usage of the std::move correct on the main function?
Is it okay to simply create the std::shared_ptr on main and move ownership using the AddToVec function?
Is the usage of the std::move correct on the main function?
Yes, it is correct. If you do not use the std::move, it will also compile; however, it increases the reference count of std::shared_ptr.
Is it okay to simply create the shared ptr on main and move ownership using the AddToVec function?
It is correct in the sense, you do not want to increment the reference count of the std::shared_ptr.
The same you need inside AddToVec, as the b is lvalue reference inside the function scope. Therefore, you need to explicitly std::move into the myVec_ as follows:
void AddToVec(std::shared_ptr<B> b)
{
myVec_.push_back(std::move(b));
}
Also note that the GetVec will return each time a copy of the member myVec_, which you might not want. Therefore, you might need one or both the following
// non-const reference to the member
std::vector<std::shared_ptr<B>>& GetVec()
{
return myVec_;
}
// const reference to the member
const std::vector<std::shared_ptr<B>>& GetVec() const /* noexcept */
{
return myVec_;
}
Related
Lets consider the following piece of code:
template<typename T>
void f(std::unique_ptr<T>&& uptr) { /*...*/ }
In another function:
void g()
{
std::unique_ptr<ANY_TYPE> u_ptr = std::make_unique<ANY_TYPE>();
f(std::move(u_ptr));
X: u_ptr->do_sth(); // it works, I don't understand why. Details below.
}
I don't understand why u_ptr in line X is still alive.
After all I forced him to be moved (std::move).
---EDIT---
Ok, so now:
The code is still working:
class T{
public:
T(){}
void show(){
std::cout << "HEJ!\n";
}
};
void f(std::unique_ptr<T> ref){
ref->show();
}
int main()
{
std::unique_ptr<T> my;
my->show();
f(std::move(my));
my->show(); // How is it possible. Now, f takes unique_ptr by value
return 0;
}
You didn't show us that code to function f, but presumably it didn't move the pointer, even though it had permission to.
You passed the unique_ptr by reference. If function invocation actually moved it, then the function couldn't use it because it would be gone before the function had a chance to.
If you want function invocation to actually move the pointer, you need to pass the pointer by value, not be reference. That value would be a unique_ptr for it to be moved into. In that case, you should declare the function as taking a std::unique_ptr<T> instead of a std::unique_ptr<T>&&. Then you can actually invoke the move constructor when you call the function.
Update: With your latest change, the unique_ptr would no longer reference any valid object due to the move construction. You just never check that it does. Invoking a non-virtual method that doesn't access any member variables can work just the same whether the object is valid or destroyed because it doesn't need anything from the object. You also never made the unique_ptr actually point to anything.
Instead, make the unique_ptr point to something. After it's moved, try calling a virtual function or accessing a member whose value is changed by the destructor. Like this:
#include <iostream>
#include <memory>
class T{
public:
T() : valid (true) {}
~T() { valid = false; }
bool valid;
void show(){
std::cout << "HEJ! " << valid << std::endl;
}
};
void f(std::unique_ptr<T> ref){
ref->show();
}
int main()
{
std::unique_ptr<T> my (new T); // Make it point to a new object
my->show();
f(std::move(my));
my->show(); // Try to access
return 0;
}
in the line f(std::unique_ptr<T>&& uptr) uptr is not an object - it's a reference. a reference which capable to catch temporeries and mutate them.
it's like asking why doesn't the object get cloned in the next example
void func(std::string& str);
std::string str_ = "yyy";
func(str_);
str_ is passed by "regular" reference and won't get copied - this is what pass by reference means.
std::move only cast l-value to r-value-reference, which uptr in f(std::unique_ptr<T>&& uptr) can reference, it's a reference referencing an object. opposed to the common conception, std::move won't do any moving by itself, only casts the object to r-value-reference for the move constructor/assg. operator to kick in.
here, the pointer still holds valid data since it was not moved, only casted to r-value-reference.
if you want the object to move you have to declare the parameter as object, not reference : f(std::unique_ptr<T> uptr)
In your edit, you have undefiend behaviour, so everything may occure.
The reason why your call to show doesn't crash is because it doesn't use the this pointer (it doesn't try to modify or access a data member).
Try this:
class T{
public:
int v;
T(){}
void show(){
v = 0;
std::cout << "HEJ!\n";
}
};
void f(std::unique_ptr&& ref)
This is the answer when you initially had your f function taking a rvalue reference &&.
Your function takes a rvalue reference. Therefore, no new unique_ptr object is created yet, you are simply passing a reference.
Inside your f function, if you create a a local unique_ptr, with the parameter uptr, then finally uptr will be moved to create that new object.
template<typename T>
void f(std::unique_ptr<T>&& uptr)
{
//move uptr into local_unique_ptr
//note that we have to use move again
//because uptr has a name, therefore its a lvalue.
auto local_unique_ptr = std::unique_ptr<T>(std::move(uptr));
}
The important thing to always know is that std::move is simply a static_cast.
If you pass a lvalue to std::move, it returns a rvalue. If you pass a rvalue, it returns a rvalue. That's it.
Your function f may not in fact move the pointer. Merely taking an object by && does not modify the object.
u_ptr->do_sth() may invoke a static member function or a member function that does not access the object (this) and this is why it does not crash.
I am new to C++11. In fact until recently, I programmed only using dynamic allocation, in a way similar to Java, e.g.
void some_function(A *a){
a->changeInternalState();
}
A *a = new A();
some_function(a);
delete a;
// example 2
some_function( new A() ); // suppose there is **no** memory leak.
Now I want to reproduce similar code with C++11, but without pointers.
I need to be able to pass newly created class class A directly to function useA(). There seems to be a problem if I want to do so with non-const normal reference and It works if I do it with rvalue reference.
Here is the code:
#include <stdio.h>
class A{
public:
void print(){
++p; // e.g. change internal state
printf("%d\n", p);
}
int p;
};
// normal reference
void useA(A & x){
x.print();
}
// rvalue reference
void useA(A && x){
useA(x);
}
int main(int argc, char** argv)
{
useA( A{45} ); // <--- newly created class
A b{20};
useA(b);
return 0;
}
It compiles and executes correctly, but I am not sure, if this is the correct acceptable way to do the work?
Are there some best practices for this kind of operations?
Normally you would not design the code so that a temporary object gets modified. Then you would write your print function as:
void useA(A const & x){
x.print();
}
and declare A::print as const. This binds to both rvalues and lvalues. You can use mutable for class member variables which might change value but without the object logically changing state.
Another plan is to keep just A &, but write:
{ A temp{45}; useA(temp); }
If you really do want to modify a temporary object, you can write the pair of lvalue and rvalue overloads as you have done in your question. I believe this is acceptable practice for that case.
The best thing about C++11 move semantics is that most of the time, you get them "for free" without having to explicitly add any &&s or std::move()s in your code. Usually, you only need to use these things explicitly if you're writing code that does manual memory management, such as the implementation of a smart pointer or a container class, where you would have had to write a custom destructor and copy constructor anyway.
In your example, A is just an int. For ints, a move is no different from a copy, because there's no opportunity for optimization even if the int happens to be a disposable temporary. Just provide a single useA() function that takes an ordinary reference. It'll have the same behavior.
So say I was using this to create an object:
MyClass myObject;
and I had the function inside of the class to act upon the object. So one way could be using parameters, like this:
MyClass foo(MyClass a) {
return a;
}
Seems simple. But is there a way so I can use myObject.foo() and it would still return a even though I'm not using it as a parameter? One example could be some of the methods in std::string - you can use std::string.swap(), using the object for the swap() function.
Is there a way, or am I being stupid?
First off, keep in mind that you original code of
MyClass foo(MyClass a) {
return a;
}
does not actually return a. It returns a copy of a, which itself is a copy of whatever instance of MyClass you passed into foo. If you want to pass in a given object, act on it and return it, you need to use references, like so
MyClass & foo(MyClass & a) {
return a;
}
This will ensure that the a you get back from a call to foo is the exact same object you passed into it.
Additionally, an object can always return a reference to itself in one of its members...
class MyClass {
MyClass & foo() { return *this; }
}
This is especially useful in classes where you might want to chain a large number of operations together...
MyClass my = MyClass().foo().bar("Hello").baz(5);
Inside every member function is a magic secret parameter, which is a pointer to the object who's method was called, and the parameter's name is this.
MyClass& foo() { //returns reference to existing MyClass instead of making copies
this->print(); //call a different member
return *this; //return a reference to itself. Common for `operator=` and such.
}
Inside a class's (non-static) member function, you can use *this to name the object the function was called on.
So:
MyClass MyClass::foo() {
return *this;
}
(Notice that function returns a copy of the object. If you don't want a copy, use a reference as in #Jherico's answer.)
I have a class defined like:
class Foo
{
public:
void ReturnReferenceToMember(???)
{
??? // Give caller a reference to member variable m_x
}
private:
std::unordered_map<int, int> m_x;
}
What's the C++ way to implement the ????
I don't want to copy the internals of the map, and I also want to keep being able to use the map inside the class. I don't understand move mechanics that well, but it seems to me like the second requirement negates std::move...
It is not possible to pass a reference that can be changed. That would mean passing a pointer to a reference, or a reference to a reference - both of those are invalid in C++.
The usual approach is to return a reference, not (since it can't be done) to pass one in the hope of it being changed.
std::unordered_map<int, int>& ReturnReferenceToMember()
{
return m_x;
}
If you expect to pass an argument that can be changed in order to permit the caller to access class internals, it is necessary to use a pointer to a pointer
// double indirection needed as pointers are passed by value too
void ReturnPointerToMember(std::unordered_map<int, int> **p)
{
*p = &mx;
}
or a reference to a pointer
void ReturnPointerToMember(std::unordered_map<int, int> *&p)
{
p = &mx; // note the missing asterisk compared with passing pointer to pointer
}
If you don't wish the caller to change class internals, it is necessary to const-qualify the above in various ways.
void ReturnReferenceToMember(std::unordered_map<int, int>** outMap)
{
*outMap = &m_x;
}
void ReturnReferenceToMember(const std::unordered_map<int, int>** outMap) const
{
*outMap = &m_x;
}
I overloaded it on const intentionally, so you can use either form depending on whether the Foo you have is const.
As you can see, we are not really using references here, because those cannot be reseated, but the caller can still use them:
std::unordered_map<int, int>* mapPtr = nullptr;
ReturnReferenceToMember(&mapPtr);
if (mapPtr)
{
std::unordered_map<int, int>& mapRef = *mapPtr;
// now you have your reference
}
I have a "sum" class which holds two references to existing ints (say). I want to create a "copy" method which deep copies the ints. I thought I would never have to manually delete objects in my code, thanks to smart pointers, but I had to in this solution. Moreover, it is too complicated for a so trivial task (which I need to repeat for several classes). Is there a more straightforward solution?
Note: I don't want to add a bool member (flag) to each objects to determine if the ints must be deleted (in my case, it's not a better overhead than the std::set check overhead in the destructor)
#include <set>
struct sum {
const int &a, &b;
static std::set<const int*> allocated_ints;
sum(const int& a, const int&b): a(a), b(b) {}
sum copy() const {
sum res(*new const int(a), *new const int(b));
allocated_ints.insert(&res.a);
allocated_ints.insert(&res.b);
return res;
}
~sum() {
if (allocated_ints.count(&this->a)) {
delete &this->a;
delete &this->b;
allocated_ints.erase(&this->a);
allocated_ints.erase(&this->b);
}
}
};
std::set<const int*> sum::allocated_ints;
What's the point of a "deep" copy of constants? The constants are going to have the same value no matter what! So just copy (i.e. alias) the const-references:
struct Foo
{
const int & n;
Foo(const int & m) : n(m) { }
Foo(const Foo & rhs) : n(rhs.n) { }
Foo copy() const { Foo f(*this); /* ... */ return f; }
// ...
};
If you're worried about dangling references when returning a copy from a function with a reference to a local variable, then don't make the class have const references, but copies. That way you naturally give your class the copy semantics that you seem to be after anyway.
If you were thinking that you could make a hybrid which is either non-owning or becomes owning depending on how you use it, then I'd say that's bad design that you should avoid. Decide whether your class has ownership over the data or not and then roll with it.
I think you're mixing-up two incompatible concepts.
If you initialize by reference you should refer to existing object whose lifetime is already defined and should be longer than your objects.
If you want to create a copy of your object, since it refers to something, your copy will also refer to that something.
If you want to own yourself dynamic supplied objects, you should use pointers for that, and acquire them as pointers (and delete them on destruction). A copy can then deep-create copies of the pointed objects (or can share them using reference counting or shared_ptr).
You are -in fact- making up a mixing of the two things, resulting in possible problems: think to:
int main()
{
const int x=5; //whatever it is
Foo foo(x);
// ...
} //danger here! ~Foo() will delete x
The references are not deep copied, because they point to an object. Therefore, your code fixed should look like this :
struct sum {
const int &a, &b;
sum(const int& a, const int&b): a(a), b(b) {}
sum copy() const {
sum res(a,b);
return res;
}
~sum() {
}
};