Jump to content

  • Log In with Google      Sign In   
  • Create Account


#ActualServant of the Lord

Posted 24 March 2013 - 06:58 PM

SiCrane is saying you can use the second template parameter of smart pointers to give a fake custom deleting function (in this case, a functor), so shared_ptr can work with stack-allocated variables.
 
//Functor for pretending to delete a block of stack-allocated memory, instead of using the default deleter provided by smart pointers.
//This can be passed as the second parameter of a smart pointer.
struct do_not_delete
{
    do_not_delete() { }
    
    void operator()(void*) const
    {
        //Do nothing. Let the stack free the memory when it's ready.
    }
};

{
	std::string onTheStack = "Test";
	{
		std::shared_ptr<std::string> mySharedPtr(&onTheStack, do_not_delete());	
		std::cout << *mySharedPtr << std::endl;
	}
	//mySharedPtr goes out of scope here, and calls 'do_not_delete(ptr)' to free the memory,
	//but do_not_delete doesn't free it, safely letting the stack-allocated memory continue to exist.

	std::cout << onTheStack << std::endl; //The stack-allocated memory continues to work just fine.
}
(I'm using C++11's standard shared pointers, but it should be roughly the same for boost smart pointers)

Ofcourse, now you have to be sure that 'onTheStack' lasts longer than 'mySharedPtr', or hard-to-track bugs result.

However, I think your low level functions shouldn't take pointers at all! I think almost every function should take parameters by const reference, unless something else is required. Then, whether you pass in actual stack-allocated or heap-allocated, it doesn't matter, and the function doesn't care.
void myFunc(const std::string &str);

std::string stackAllocated;
myFunc(stackAllocated);

std::shared_ptr<std::string> heapAllocatedShared = std::make_shared<std::string>();
myFunc(*heapAllocatedShared);

std::unique_ptr<std::string> heapAllocatedUnique = make_unique<std::string>();
myFunc(*heapAllocatedUnique);
You said that your low-level system "shares" data. Does it 'own' the data, or just 'use' the data? If it doesn't own it, it shouldn't be a shared_ptr, because shared_ptr means shared ownership. If something else owns it higher up, just use references or raw pointers lower down, unless it is possible for the lifetime of the system's access to the pointers to extend beyond the lifetime of the data passed in. If the lower down system uses it, but does not own it, and is likely to keep the pointer around for longer than the lifetime of the memory allocated, it might be worth considering whether that lower-level system should actually own it, with higher level code creating the object and giving up ownership of it to the lower system. Or maybe the lower-level system actually is doing more than it should be doing? Software architecture-design isn't my strong point.

#3Servant of the Lord

Posted 24 March 2013 - 06:56 PM

SiCrane is saying you can use the second template parameter of smart pointers to give a fake custom deleting function (in this case, a functor), so shared_ptr can work with stack-allocated variables.
 
//Functor for pretending to delete a block of stack-allocated memory, instead of using the default deleter provided by smart pointers.
//This can be passed as the second parameter of a smart pointer.
struct do_not_delete
{
    stack_allocated_deleter() { }
    
    void operator()(void*) const
    {
        //Do nothing. Let the stack free the memory when it's ready.
    }
};

{
	std::string onTheStack = "Test";
	{
		std::shared_ptr<std::string> mySharedPtr(&onTheStack, do_not_delete());	
		std::cout << *mySharedPtr << std::endl;
	}

	std::cout << onTheStack << std::endl;
}
(I'm using C++11's standard shared pointers, but it should be roughly the same for boost smart pointers)

Ofcourse, now you have to be sure that 'onTheStack' lasts longer than 'mySharedPtr', or hard-to-track bugs result.

However, I think your low level functions shouldn't take pointers at all! I think almost every function should take parameters by const reference, unless something else is required. Then, whether you pass in actual stack-allocated or heap-allocated, it doesn't matter, and the function doesn't care.
void myFunc(const std::string &str);

std::string stackAllocated;
myFunc(stackAllocated);

std::shared_ptr<std::string> heapAllocatedShared = std::make_shared<std::string>();
myFunc(*heapAllocatedShared);

std::unique_ptr<std::string> heapAllocatedUnique = make_unique<std::string>();
myFunc(*heapAllocatedUnique);
You said that your low-level system "shares" data. Does it 'own' the data, or just 'use' the data? If it doesn't own it, it shouldn't be a shared_ptr, because shared_ptr means shared ownership. If something else owns it higher up, just use references or raw pointers lower down, unless it is possible for the lifetime of the system's access to the pointers to extend beyond the lifetime of the data passed in. If the lower down system uses it, but does not own it, and is likely to keep the pointer around for longer than the lifetime of the memory allocated, it might be worth considering whether that lower-level system should actually own it, with higher level code creating the object and giving up ownership of it to the lower system. Or maybe the lower-level system actually is doing more than it should be doing? Software architecture-design isn't my strong point.

#2Servant of the Lord

Posted 24 March 2013 - 06:56 PM

SiCrane is saying you can use the second template parameter of smart pointers to give a fake custom deleting function, so shared_ptr can work with stack-allocated variables.
 
//Functor for pretending to delete a block of stack-allocated memory, instead of using the default deleter provided by smart pointers.
//This can be passed as the second parameter of a smart pointer.
struct do_not_delete
{
    stack_allocated_deleter() { }
    
    void operator()(void*) const
    {
        //Do nothing. Let the stack free the memory when it's ready.
    }
};

{
	std::string onTheStack = "Test";
	{
		std::shared_ptr<std::string> mySharedPtr(&onTheStack, do_not_delete());	
		std::cout << *mySharedPtr << std::endl;
	}

	std::cout << onTheStack << std::endl;
}
(I'm using C++11's standard shared pointers, but it should be roughly the same for boost smart pointers)

Ofcourse, now you have to be sure that 'onTheStack' lasts longer than 'mySharedPtr', or hard-to-track bugs result.

However, I think your low level functions shouldn't take pointers at all! I think almost every function should take parameters by const reference, unless something else is required. Then, whether you pass in actual stack-allocated or heap-allocated, it doesn't matter, and the function doesn't care.
void myFunc(const std::string &str);

std::string stackAllocated;
myFunc(stackAllocated);

std::shared_ptr<std::string> heapAllocatedShared = std::make_shared<std::string>();
myFunc(*heapAllocatedShared);

std::unique_ptr<std::string> heapAllocatedUnique = make_unique<std::string>();
myFunc(*heapAllocatedUnique);
You said that your low-level system "shares" data. Does it 'own' the data, or just 'use' the data? If it doesn't own it, it shouldn't be a shared_ptr, because shared_ptr means shared ownership. If something else owns it higher up, just use references or raw pointers lower down, unless it is possible for the lifetime of the system's access to the pointers to extend beyond the lifetime of the data passed in. If the lower down system uses it, but does not own it, and is likely to keep the pointer around for longer than the lifetime of the memory allocated, it might be worth considering whether that lower-level system should actually own it, with higher level code creating the object and giving up ownership of it to the lower system. Or maybe the lower-level system actually is doing more than it should be doing? Software architecture-design isn't my strong point.

#1Servant of the Lord

Posted 24 March 2013 - 06:54 PM

SiCrane is saying you can use the second template parameter of smart pointers to give a fake custom deleting function, so shared_ptr can work with stack-allocated variables.
 
//Functor for pretending to delete a block of stack-allocated memory, instead of using the default deleter provided by smart pointers.
//This can be passed as the second parameter of a smart pointer.
struct do_not_delete
{
    stack_allocated_deleter() { }
    
    void operator()(void*) const
    {
        //Do nothing. Let the stack free the memory when it's ready.
    }
};

{
	std::string onTheStack = "Test";
	{
		std::shared_ptr<std::string> mySharedPtr(&onTheStack, do_not_delete());	
		std::cout << *mySharedPtr << std::endl;
	}

	std::cout << onTheStack << std::endl;
}
(I'm using C++11's standard shared pointers, but it should be roughly the same for boost smart pointers)

Ofcourse, now you have to be sure that 'onTheStack' lasts longer than 'mySharedPtr', or hard-to-track bugs result.

However, I think your low level functions shouldn't take pointers at all! I think almost every function should take parameters by const reference, unless something else is required. Then, whether you pass in actual stack-allocated or heap-allocated, it doesn't matter, and the function doesn't care.
void myFunc(const std::string &str);

std::string stackAllocated;
myFunc(stackAllocated);

std::shared_ptr<std::string> heapAllocatedShared = std::make_shared<std::string>();
myFunc(*heapAllocatedShared);

std::unique_ptr<std::string> heapAllocatedUnique = make_unique<std::string>();
myFunc(*heapAllocatedUnique);
You said that your low-level system "shares" data. Does it 'own' the data, or just 'use' the data? If it doesn't own it, it shouldn't be a shared_ptr, because shared_ptr means shared ownership. If something else owns it higher up, just use references or raw pointers lower down, unless it is possible for the lifetime of the system's access to the pointers to extend beyond the lifetime of the data passed in. If the lower down system uses it, but does not own it, and is likely to keep the pointer around for longer than the lifetime of the memory allocated, it might be worth considering whether that lower-level system should actually own it, with higher level code creating the object and giving up ownership of it to the lower system.

PARTNERS