How to use a unique_ptr after passing it to a function? - c++

I just started learning the new C++ memory model:
#include <string>
#include <iostream>
#include <memory>
void print(unique_ptr<std::string> s) {
std::cout << *s << " " << s->size() << "\n";
}
int main() {
auto s = std::make_unique<std::string>("Hello");
print(std::move(s));
std::cout << *s;
return 0;
}
Right now calling cout << *s; results in a segfault, as it should. I understand why it happens. But I also would like to know if there's a way get back the ownership. I'd like to be able to use a value after passing it to a function.

If you don't want to transfer ownership of the owned object, then don't pass the unique_ptr to the function. Instead, pass a reference or a raw pointer to the function (in modern C++ style, a raw pointer is usually understood to be non-owning). In the case where you just want to read the object, a const reference is usually appropriate:
void print(const std::string&);
// ...
print(*s);

Related

Initialize a string with a char pointer with zero-copy

Say I am given a long and null-terminated cstring as char* text_ptr. I own text_ptr and I am responsible of free()ing it. Currently, I use text_ptr and free() it each time after use.
I try to improve memory safety a bit by wrapping it in a C++ class so that I can enjoy the benefit of RAII. There could be many ways to achieve it. A naive way is: string text_ptr(text_ptr);. However, by doing so, memory is copied once and I still need to manually free() my text_ptr. It would be better if I can avoid memory copy and free() (as this text_ptr is created frequently, performance could take a big hit if I copy it each time). My current thought:
Is it possible to transfer the ownership of text_ptr to a string text_str? Hypothetically, I do text_str.data() = text_ptr;.
Thanks
std::string can't receive ownership of an external buffer. The best you can do is std::unique_ptr.
By default std::unique_ptr will use delete (or delete[]), but you need std::free(), so a custom deleter is required:
#include <cstdlib>
#include <memory>
struct FreeDeleter
{
void operator()(void *p) const
{
std::free(p);
}
};
int main()
{
std::unique_ptr<char[], FreeDeleter> ptr((char *)malloc(42));
}
If you also store the length, you can construct a temporary std::string_view from pointer+length when needed, to conveniently read the string.
Or, a oneliner: std::unique_ptr<char[], std::integral_constant<void(*)(void *), std::free>>.
Another one for C++20: std::unique_ptr<char[], decltype([](void *p){std::free(p);})>.
An idea (not sure it’s a good one, tho)
#include <iostream>
#include <string_view>
#include <cstring>
#include <memory>
struct my_string_view : public std::string_view
{
using std::string_view::string_view;
std::shared_ptr<char[]> _data;
explicit my_string_view( char * data )
: std::string_view(data)
, _data{data, free}
{ }
};
void f( const my_string_view & s )
{
std::cout << "f: \"" << s << "\"\n";
}
int main()
{
my_string_view s( strdup( "Hello world!" ) );
f( s );
std::cout << "main: \"" << s << "\"\n";
}
(This version requires C++17. For older versions of the standard you’ll have to specify the default_deleter<char[]>() explicitly.)

create a closure for a lambda in c++

is this the correct way to create a closure for a lambda function
#include <functional>
#include <memory>
#include <string>
#include <iostream>
using namespace std;
class A
{
function<void()> fn(string str){ // (2)
struct closure {
int num;
};
auto ptr = make_shared<closure>();
ptr->num = 99;
auto fn = [=](){
ptr->num++;
cout << ptr->num << " -- " << str << endl;
};//fn
return fn;
}//fn
};//A
A a;
int main(){
auto fn = a.fn("1");
fn();
fn();
auto fn2 = a.fn("2");
fn2();
fn2();
}//main
view code -> online c++ compiler
the arguments to the function that creates the lambda #(2) dont seem to be needed within the closure, is this actually true?
what are the caveats to using this approach, heap/stack = creme fraiche, do i need to release the memory?
what practical difference would it make to capture by reference within the lambda?
edit
maybe i over simplified, sometimes the function looks like this
class A {
void fn(string str){
struct closure {
int num;
int token;
};
auto ptr = make_shared<closure>();
ptr->num = 100;
auto fn = [=](){
ptr->num++;
cout << str << ptr->num << endl;
if(ptr->num==105){
list.rem(ptr->token); // <= defined elsewhere
}
};
ptr->token = list.add(fn); // <= defined elsewhere
}//fn
};//A
is this the correct way to create a closure for a lambda function?
Your lambda can be simplified to:
function<void()> fn(string str){
return [str, i = 99]() mutable {
++i;
std::cout << i << " -- " << str << std::endl;
};
}
do I need to release the memory?
You capture a std::shared_ptr by value, it would release its memory on destruction, you are fine.
what practical difference would it make to capture by reference within the lambda?
As you capture local variable, capturing by reference would lead to dangling pointer.
It looks like it isn't wrong, but for what it is also looks like massive overkill.
You could accomplish the same thing without using sharerd_ptr or any dynamic memory, by simply capturing an int and making the lambda mutable:
std::function<void()> fn(std::string str){ // (2)
return [=, num = 99]() mutable {
num++;
std::cout << num << " -- " << str << "\n";
};
}
If you plan to copy your lambda and have both copies affect the same underlying data, OR, you hold onto that shared pointer and do more things with it, possibly after returning the lambda, then perhaps your approach makes more sense. A custom struct and shared ptr is heavy and I prefer simple whenever possible.
Also, the by-value / by-reference question is important, since str is printed out in the lambda, it needs to be sure that the object it uses continues to live. Since it is a function parameter, the argument will be destroyed when the function returns, so the lambda must not store a reference to it, or it'll be to a destructed object and cause undefined behavior if it's called. You need the copy to preserve the string so it's guaranteed to be valid when the lambda is called.

Trying to get to grips with C++ and cant work out why this doesn't print out the names of the vector<string> entries

So this code doesn't print out the entries inside of the vector gameLibrary
Originally I just used the gameLibrary.pushback(" ") function to add them and that worked fine.
I'm more just trying to get to grips with why this doesn't work. when ( at least in my mind it's doing the same thing)
#include <iostream>
#include <vector>
#include <string>
using std::cout;
using std::vector;
using std::string;
void addGame(vector<string> gameLibrary, string gameName);
int main()
{
vector<string> gameLibrary;
vector<string>::iterator editIter;
addGame(gameLibrary, "game");
addGame(gameLibrary, "game 2");
cout << "Your library: " << std::endl;
for (editIter = gameLibrary.begin(); editIter != gameLibrary.end(); ++editIter)
{
cout << *editIter << std::endl;
}
return 0;
}
void addGame(vector<string>gameLibrary, string gameName)
{
gameLibrary.emplace_back(gameName);
}
addGame must not receive the vector it is filling by copy. It must be passed by reference or by pointer.
Exemple passing by reference :
void addGame(vector<string>& gameLibrary, string gameName)
{
gameLibrary.emplace_back(gameName);
}
Otherwise, the copy is modified, so the vector declared in main is unchanged.
Please read up on passing by value vs reference. In your function you are passing your array by value, which means that only the value of your array gets copied into the function.
Any changes to the array insider the function are not reflected back. If you need that, you need to pass your array by reference
see this answer : Are vectors passed to functions by value or by reference in C++

Segmentation fault on class when declared as pointer

So I’m in the process of creating an event style system, but this code breaks when I declare a connection as a pointer.
#include <iostream>
#include <chrono>
#include <thread>
using namespace std;
using namespace chrono_literals;
template<typename... Types>
struct Connection {
void Connect(void(*f)(Types...)) {
Callback = f;
}
void Fire(Types... Args) {
Callback(Args...);
}
private:
void(*Callback)(Types...);
};
int main() {
cout << boolalpha;
Connection<char>* event;
event->Connect([](char key){
cout << "Event fired!" << '\n';
cout << "Key: " << key << '\n';
});
event->Fire('a');
}
This code works when the connection isn’t a pointer, and instead of using the -> operator, I’d use use the regular . operator, but I’d like to declare them as pointers so I can use the -> .
One very strange thing to note is when I do something like this
Connection<char> e;
Connection<char>* event;
// ... rest of code
Then this actually runs, I don’t know why it’s like that.
You don't "declare a class as a pointer". That's not a thing. You have a class (which is a type), then you declare an instance of that class (i.e. an object). Optionally you can manage that object using pointers.
But you didn't actually create any instance. All you did was create a pointer, uninitialised, not pointing to anything, then tried to dereference it to use the object it points to… which doesn't exist.
There's no need for dynamic allocation here anyway; forget the pointer and just declare a nice Connection<Event>. Using pointers "because it looks nicer" is, to put it kindly, not the best way to write a C++ program.

C++ bind to weak_ptr not working

I have a simple test where I am trying to bind a weak_ptr argument to a global function that takes a weak_ptr, and invokes a method if the backing pointer is still valid.
This seems to work when I create a lambda with the weak pointer. It also works if I call the global method directly, with the weak_ptr. However if I bind the global function to the weak_ptr in advance, it does not seem to work. Following watered down code illustrates the question.
I must be missing something simple. Any clues?
#include <iostream>
#include <functional>
#include <algorithm>
#include <memory>
using namespace std;
class MyValue : public enable_shared_from_this<MyValue>
{
public:
MyValue (int i)
{
value = i;
}
~MyValue()
{
}
int getValue() { return value; }
void printValue() { cout << value << endl; }
private:
int value;
};
void callWeakFunction (weak_ptr<MyValue> weakValue)
{
shared_ptr<MyValue> strongPtr = weakValue.lock();
if (strongPtr)
{
strongPtr->printValue();
}
else
{
cout << "Sorry, your backing pointer is gone" << endl;
}
}
int main()
{
weak_ptr<MyValue> weakValue;
// Try binding a global function to the weak pointer, doesn't seem to work
function<void()> weakPrintValue = bind(callWeakFunction, weakValue);
#if 0
// Create a lambda - this works fine
function<void()> weakPrintValue ([&weakValue]()
{
shared_ptr<MyValue> ptr = weakValue.lock();
if(ptr)
{
ptr->printValue();
}
else
{
cout << "Sorry, backing pointer is gone" << endl;
}
});
#endif
{
shared_ptr<MyValue> value = make_shared<MyValue>(7);
weakValue = value;
// Backing pointer is present
weakPrintValue(); // This does not work, but callWeakFunction (weakValue) works fine
}
// No backing pointer
weakPrintValue();
}
Resulting output:
Sorry, your backing pointer is gone
Sorry, your backing pointer is gone
Expecting the first weakPrintValue to print the value (7)
I think you want to wrap the weak_ptr in ref() to evaluate it lazily:
function<void()> weakPrintValue = bind(callWeakFunction, ref(weakValue));
I wouldn't expect either to work. In both cases you're capturing the initial value of weak_value when it is empty. To be affected by the subsequent assignment to it you need to capture by reference instead. So in the lambda you need [&weak_value], and for the bind you need
bind(callWeakFunction, cref(weakValue));
I believe bind() captures weakValue by value. It returns resulting object that has it's own copy of weakValue. When you change local weakValue it does not affect the copy inside of the object returned by bind().