用于运行时识别的编译时间字符串分配
Posted
技术标签:
【中文标题】用于运行时识别的编译时间字符串分配【英文标题】:Compile time string assignment for run-time identification 【发布时间】:2013-07-21 23:04:56 【问题描述】:我一直在我正在创建的库中使用一种模式,该模式使用将对象的字符串名称传递给其基础对象的构造函数。我尝试过使用 std::string 和 c 风格的字符串,但 Valgrind 不断出现奇怪的内存错误。
class Base
public:
Base( std::string name ) : name(name)
virtual ~Base()
std::string getName() return name;
private:
std::string name;
;
class Derived : public Base
public:
Derived() : Base("Derived")
;
int main()
Base* derived = new Derived;
std::cout << derived->getName() << "\n";
delete derived;
(这在 Valgrind 中编译并运行良好)
这样的东西安全吗?我现在使用 'const char*' 而不是 'std::string',这样安全吗?
有没有更安全的选择,最好不使用虚拟机?
编辑:有没有办法用模板做到这一点?我不想使用 RTTI,因为它的名称被破坏了,我希望名称是“正常的”以用于脚本/数据持久性。
【问题讨论】:
您的基类需要有一个虚拟析构函数(这可能是您看到的错误的原因)。此外,您可能应该使用unique_ptr
或shared_ptr
而不是原始指针。
刚刚检查过,我的代码中所有的碱基都是虚拟的。
对于字符串常量,不要像std::unique_ptr< char const[] >( "hello" )
那样使用智能指针,因为char const *
指向静态数据存储,而不是堆。而且我在这里看不到问题,这段代码安全且没问题,但显然不代表有问题的部分。
好的,谢谢,这就是我要问的。我已经阅读了有关字符串静态初始化问题的帖子,并且在将 CStrings 切换到 std::strings 时遇到了奇怪的错误。只是想确保这是安全的。
【参考方案1】:
你在这里做的一切都很好。
模板不会为您带来任何好处,因为您仍然需要在基类中存储运行时指针以进行动态识别。
智能指针不会为您带来任何好处,因为字符串的生命周期就是整个程序。如果你不计算任何东西,char const *
和从字符串文字初始化是理想的。如果您正在计算字符串,那么您可以使用包装在 getter 函数中的static std::string const
。
class Derived : public Base
public:
Derived() : Base(get_name())
private:
static std::string const & get_name()
static std::string const name = "Derived"; // or = compute_name();
return name;
;
这避免了静态初始化顺序的惨败。 (getter 函数从编译器接收一个额外的多线程安全保护。)string
的生命周期是程序的生命周期。 Base
可以存储string const &
或char const *
,这并不重要。我会推荐char const *
,因为string
引用可能会意外地被临时初始化。
【讨论】:
买家注意:Visual C++ 没有实现函数局部静态的线程安全初始化。 @Casey 你确定吗?这不是一个复杂的功能。 非常确定。 Here's a question about VS2010.我亲自研究过VS2012。显然是planned for "post-2013 release"。 @Casey 我会被诅咒的,就是这样。如果在每个static
本地初始化周围插入一些样板文件代表真正的编程工作,那么该编译器内部一定非常笨拙。以上是关于用于运行时识别的编译时间字符串分配的主要内容,如果未能解决你的问题,请参考以下文章