我正在使用一个库来返回对我的引用 我需要将此引用用作class-attribute 无法直接在构造函数中初始化属性(之前需要使用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相反,我的类有一个私有的复制构造函数。这意味着我无法将对象复制到新对象中。
答案 0 :(得分:6)
如果仅由参考提供,则表示您不对内存管理负责,而这反过来意味着您无法使用您自己的内存管理。也就是说,您不应该使用任何类型的智能指针来保存该对象。
虽然您可以使用&
运算符获取实际对象的地址,但是当shared_ptr
超出范围并尝试释放内存和库时,这样做会导致未定义的行为本身试图释放它自己的记忆。
答案 1 :(得分:2)
您根本无法获取参考地址。
但是,您可以使用shared_ptr<string>
并使用&getStringReference
对其进行初始化。但这会导致shared_ptr尝试删除字符串,导致它失败,因为它从未使用new分配。要解决此问题,请复制一份:
testString_.reset(new std::string(getStringReference()))
更好的是,让您的班级直接存储参考。你根本不需要打扰内存管理:
class Foo
{
std::string& _testString;
// ...
}
答案 2 :(得分:1)
您可以考虑使用支持Boost.Optional的optional references。这样,您可以延迟初始化引用,而不像使用shared_ptr
那样获取引用对象的所有权:
#include <iostream>
#include <string>
#include <boost/optional.hpp>
//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()
{
//do some initialization of the library here...
//now init the optional reference
testString_.reset( getStringReference() );
}
std::string getString() const
{
return *testString_;
}
private:
boost::optional< std::string& > testString_; //<-- note the use of optional
};
//and a main to be compilable and check if the above works...
int main()
{
Foo foo;
std::cout << foo.getString() << std::endl;
}
答案 3 :(得分:1)
立即停止使用shared_ptr
。分享不是单方面的决定。
话虽如此,您将返回对对象的引用,而不是对象的引用。你可以做两件事:
我绝对会建议复制,除非有理由不这样做,更容易做到正确。
如果您要复制,请在班级中使用boost::optional<LibObject>
,这样您就可以绕过初始化问题。
如果您希望使用引用,您仍然可以使用boost::optional
,它也可以使用!使用它:boost::optional<LibObject&>
,但请确保您引用的对象将存活足够长。
最后,关于初始化问题,您可以使用函数来处理初始化并直接返回引用,从而在初始化列表中初始化类的引用。
答案 4 :(得分:1)
您需要了解引用和内存管理的语义。
您可能想要的是您班级中的原始指针。我假设你不能使用引用,因为你不知道它将引用什么对象,直到你进行函数调用,所以你想做一些像ref = getRef();
你无法自动“保护”你的指针而不是“晃来晃去”,但不要认为你可以采取任何措施来纠正这种情况。您只需要查看有关如何正确使用引用/指针的文档。
答案 5 :(得分:0)
您不能将shared_ptr与引用类型一起使用,因为引用就是 - 对对象的引用。这不是一个真实的对象。
下一个示例只是您尝试执行的操作的简化版本:
int main()
{
int &* a;
}
答案 6 :(得分:0)
使用工厂功能?
class Library
{
public:
static void Init();
static LibraryThing & getThing();
};
class Foo
{
public:
static shared_ptr<Foo> Create()
{
if (!_libInit)
{
Library::Init();
_libInit = true;
}
return make_shared(new Foo(Library::getThing()));
}
private:
Foo(LibraryThing & ref) : _ref(ref)
{
}
private:
LibraryThing & _ref;
static bool _libInit;
};