我可以访问一个类(不是我编写的),它在构造函数中使用const char*
作为参数。如果我有一个字符串,我想传递作为参数的值,传递它的安全方法是什么,请记住字符串和类对象可能有不同的范围?
我无法访问该课程的源代码,因此不要假设它正在做一些理智的事情,比如将字符串复制到类成员中。
作为一个具体的例子,这不起作用:
#include <iostream>
#include <string>
class example {
public:
example(const char*);
const char* str;
};
example::example(const char* a) : str(a) {}
int main() {
std::string* a=new std::string("a");
example thisDoesntWork(a->c_str());
std::cout << thisDoesntWork.str << std::endl;
delete a;
std::cout << thisDoesntWork.str << std::endl; //The pointer is now invalid
a=new std::string("b");
std::cout << thisDoesntWork.str << std::endl;
}
用这个替换构造函数(据我所知)但显然非常糟糕:
example thisDoesWorkButIsAwful((new const std::string(*a))->c_str()); //Memory leak!
类似地:
char* buffer=new char[a->size()+1];
strcpy(buffer,a->c_str()); //with #include <string.h> added up top
example(buffer);
但同样,这很容易导致内存泄漏。
我目前的主要想法是在example
周围创建一个包装类,将字符串复制到char *
缓冲区,并在缓冲区超出范围时删除缓冲区,但这似乎有点重-handed。有更简单/更好的方法吗?
答案 0 :(得分:1)
从根本上说,某些需要保留在内存中 - 要么自己动手要么要自动完成。
自动执行此操作的一种方法:
class SuperThatHoldsIt
{
std::string mString ;
SuperThatHoldsIt ( std::string const& str )
: mString ( str ) { }
} ;
class HoldingExample
: private SuperThatHoldsIt
, public example
{
holdingExample ( std::string const& string )
: SuperThatHoldsIt ( string )
, example ( mString.c_str() )
{ }
} ;
然后在std::shared_ptr
(或boost::shared_ptr
)中创建它,然后保留它。
std::string myString ( "Hello, world!" ) ;
std::shared_ptr<HoldingExample> value = std::make_shared<HoldingExample> ( myString ) ;
现在它保留了内存和结构。
注意:
HoldExample派生自两个超级的原因是构造函数的顺序将解决,因为超类总是在局部变量之前初始化。这意味着我们必须在我们自己的成员变量之前构造example
,但是我们总是可以初始化超类并使用它的成员变量。
如果将其传递给函数,例如
callFunction ( *value ) ;
如果他们在您const char*
之后放弃value
,那么您仍然会有泄漏,而您实际上无法绕过这一点。