I use boost shared_ptr to wrap a pointer. However I can only get the correct value in test_shared_ptr(), while in main(), I get the wrong value.
Expected output:
100 100Actual output:
100 -572662307
It seems that the pointer becomes invalid in that case. Any correct approach to do the job? Thanks in advance.
Below is the source code.
#include <memory>
#include <iostream>
class TestClass
{
public:
TestClass(int &i);
void print_i();
private:
int *_i;
};
TestClass::TestClass(int &i) : _i(&i)
{
}
void TestClass::print_i()
{
std::cout << *_i << std::endl;
}
void print_i(int &i)
{
std::cout << i << std::endl;
}
TestClass *test_shared_ptr()
{
std::tr1::shared_ptr<int> i(new int());
*i = 100;
print_i(*i);
return new TestClass(*i);
}
int m开发者_运维问答ain(int argc, char** argv)
{
TestClass *p = test_shared_ptr();
p->print_i();
return 0;
}
You need to pass around the shared pointer, rather than references and pointers directly to the int.
What's happening is the shared pointer is never passed anywhere outside the test_shared_ptr() function. When that function returns, the shared pointer is destroyed. When it sees that nothing else has a reference to it's memory, it destroys the memory it was pointing at.
Basically, where you are using int &i
and int *i
change both to use std::tr1::shared_ptr<int> i
.
You probably need to read up on shared pointer a bit more. Basically, they keep a reference count for the pointer they are pointing to. When they are copied, they up the reference count, and when they are destroyed the decrement it. When the reference count reaches 0 (nothing else is referencing the memory it is pointing at) it frees that memory. So, even though something is using that pointer in your case, because it did not use a shared pointer there is no way for the shared pointer to know that the memory is still being used, so it frees it.
It seems that the pointer becomes invalid in that case
Of course it becomes invalid. shared_ptr gets deleted when you leave test_shared_ptr, and i does not exist after that.
Any correct approach to do the job?
1) simply copy value of i. (use int i instead of int* i in TestClass). int is small, you won't lose anything.
or
2) use std::tr1::shared_ptr<int> instead of int* in TestClass.
The issue you are having is with your API contract.
I don't want to use shared pointer to pass variable values in TestClass's constructor, since I don't want to force the api user to use smart pointer
Your TestClass
contract is currently looking like you want the caller to maintain the int
item so that it has a lifetime longer than TestClass
.
Your test case doesn't follow this contract rule however.
Actually I want to pass object by reference instead of generic type in my application.
Passing by reference or by pointer does not have anything to do with 'generic' type.
Here is a possible fix for your code testing your API, the scope of your int is then longer then sufficiently long (untill the end of the app) to handle all usages within TestClass
TestClass *test_shared_ptr(int &i)
{
i = 100;
print_i(i);
return new TestClass(i);
}
int main(int argc, char** argv)
{
std::tr1::shared_ptr<int> i(new int());
TestClass *p = test_shared_ptr(*i);
p->print_i();
return 0;
}
What you are doing really breaks the point of shared_ptr. Basically when you pass it out of that function is it magically supposed to break and, thus, not free the pointed too memory?
No. It frees it. Are you expecting the shared_ptr to still exist outside of the function so that when "p" drops out of scope it manages to call teh shared_ptr destructor? This can't happen. p is a pointer not a shared_ptr class.
Either return a shared_ptr or return the new'd pointer and delete it yourself.
精彩评论