初始化一个引用的shared_ptr ( std::tr1::shared_ptr)
我正在使用一个库,它返回对我的引用。
我需要将此引用用作类属性。
无法直接在构造函数中初始化属性(需要之前初始化lib),我考虑使用shared_ptr进行延迟初始化:
#include <iostream>
#include <string>
#include <tr1/memory>
//This is library, cannot touch
std::string globalString = "TEST";
std::string& getStringReference()
{
return globalString;
}
//this is my class which uses the library
class Foo
{
public:
Foo() :
testString_( std::tr1::shared_ptr< std::string& >() )
{
//do some initialization of the library here...
//now init the shared_ptr
testString_.reset( getStringReference() );
}
std::string getString() const
{
return *testString_;
}
private:
std::tr1::shared_ptr< std::string& > testString_;
};
//and a main to be compilable and check if the above works...
int main()
{
Foo foo;
std::cout << foo.getString() << std::endl;
}
但不幸的是这不起作用。 g++ 给出这样的消息:
error: forming pointer to reference type ‘std::string&’
我尝试了一些其他方法来将引用获取到shared_ptr,但是没有任何效果...也许你可以给我一个提示。
注:
- 在“现实世界”而不是 std::string 中,数据类型是没有默认构造函数的类。
- 对于那些仍然想知道的人:上面只是一个简化的示例代码:)
更新:
- 在尝试应用这些建议时,我发现与示例中使用的 std::string 相反,我的类有一个私有复制构造函数。这意味着我无法将对象复制到新对象中。
I'm using a library which returns a reference to me.
I need to use this reference as class-attribute.
Not being able to initialize the attribute in constructor directly (the lib needs to be inited before), I thought about using a shared_ptr for lazy initialization:
#include <iostream>
#include <string>
#include <tr1/memory>
//This is library, cannot touch
std::string globalString = "TEST";
std::string& getStringReference()
{
return globalString;
}
//this is my class which uses the library
class Foo
{
public:
Foo() :
testString_( std::tr1::shared_ptr< std::string& >() )
{
//do some initialization of the library here...
//now init the shared_ptr
testString_.reset( getStringReference() );
}
std::string getString() const
{
return *testString_;
}
private:
std::tr1::shared_ptr< std::string& > testString_;
};
//and a main to be compilable and check if the above works...
int main()
{
Foo foo;
std::cout << foo.getString() << std::endl;
}
But unfortunately this does not work. g++ gives messages like this:
error: forming pointer to reference type ‘std::string&’
I tried some other ways to get the reference into the shared_ptr, but nothing works... Perhaps you could give me a hint.
Note:
- In "real-world" instead of std::string the datatype is a class without default constructor.
- For those who still wonder: The above is just a simplified example-code :)
UPDATE:
- While trying to apply the suggestions, I found out that contrary to the used std::string from example, my class has a private copy constructor. This means I'm not able to just copy the object into a new one.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
如果您仅通过引用提供,则意味着您不负责内存管理,而这又意味着您不能使用自己的内存管理。也就是说,您不应该使用任何类型的智能指针来保存该对象。
虽然您可以使用
&
运算符获取真实对象的地址,但是当您的shared_ptr
超出范围并尝试释放该对象时,这样做会导致未定义的行为。内存和库本身尝试自行释放内存。If you are provided by a reference only, that means that you are not responsible for memory management, and that in turns means that you cannot use your own memory management. That is, you should not use any type of smart pointer to hold that object.
While you can obtain the address of the real object with the
&
operator, doing so will cause undefined behavior later on when yourshared_ptr
goes out of scope and tries to free the memory and the library itself tries to free the memory on it's own.您根本无法获取引用的地址。
不过,您可以使用
shared_ptr
并使用&getStringReference
对其进行初始化。但这将导致shared_ptr尝试删除该字符串,从而导致它失败,因为它从未使用new分配。要解决此问题,请制作一个副本:更好的是,让您的类直接存储引用。您根本不需要担心内存管理:
You simply cannot take the address of a reference.
You can however use
shared_ptr<string>
and initialize it with&getStringReference
. But that will cause the shared_ptr to try to delete the string, causing it to fail since it was never allocated using new. To fix this, make a copy:Even better, let your class just store the reference directly. The you don't need to bother about memory management at all:
您需要了解引用和内存管理的语义。
您可能想要的是类中的原始指针。我假设您不能使用引用,因为在进行函数调用之前您不知道它将引用哪个对象,因此您想要执行类似 ref=getRef(); 的操作;
您无法自动“保护”您的指针免于“悬空”,但您也不认为可以采取任何措施来纠正这种情况。您只需查看有关如何正确使用引用/指针的文档。
You need to understand the semantics of references and of memory management.
What you probably want is a raw pointer in your class. I assume you can't use a reference because you do not know what object it will refer to until you make the function call so you want to do something like ref=getRef();
You have no way of automatically "protecting" your pointer against becoming "dangling", but do not think there is anything you can do to rectify this situation. You just have to look at the documentation as to how to use the reference/pointer properly.
您可以考虑使用 Boost.Optional ,支持可选引用 。这样,您就可以延迟初始化引用,而无需像使用
shared_ptr
那样获取引用对象的所有权:You could consider using Boost.Optional, which support optional references. This way, you could lazy initialize your reference without taking ownership of the referenced object as you do by using
shared_ptr
:立即停止使用
shared_ptr
。共享不是单方面的决定。话虽如此,您返回的是对对象的引用,而不是对象本身。您可以做两件事:
我肯定会建议复制,除非有理由不这样做,这样更容易做到正确。
如果您要进行复制,请在类中使用
boost::optional
,这样您就可以绕过初始化问题。如果您想使用参考,您仍然可以使用
boost::Optional
,它也能工作!按如下方式使用它:boost::optional
,但请确保您引用的对象能够存活足够长的时间。最后,关于初始化问题,你可以使用一个函数来处理初始化并直接返回一个引用,从而在初始化列表中初始化你的类的引用。
Stop using
shared_ptr
now. Sharing is not an unilateral decision.That being said, you are returned a reference to an object, not the object proper. There are two things you can do:
I would definitely recommend copying unless there is a reason not to, much easier to get it right.
If you go for copying, use
boost::optional<LibObject>
within your class, this way you'll bypass the initialization issue.If you wish to use a reference, you can still use
boost::optional
, and it'll work too! Use it as such:boost::optional<LibObject&>
, but make sure the object you have a reference to will live long enough.Finally, regarding the initialization issue, you could use a function to process the initialization and return a reference directly, thus initializing the reference of your class in the initialization list.
您不能将shared_ptr 与引用类型一起使用,因为引用就是对对象的引用。它不是一个真实的物体。
下一个示例只是您尝试执行的操作的简化版本:
You can not use a shared_ptr with a reference type, because a reference is just that - a reference to an object. It is not a real object.
Next example is just simplified version of what you tried to do :
使用工厂函数?
Use a factory function?