2010-03-31 161 views
3

我有一个通用数据类型,它通过值传递,但不保留类型信息。我们只在这里存储指针和基本数据类型(如int,float等)。现在第一次,我们需要在这里存储std :: string。所以我们决定将它转换成std :: string *并存储它。然后是破坏问题。我们不喜欢每次都复制std :: string。所以我正在考虑这样的方法。说的数据类型看起来像这样C++通用数据类型

class Atom 
{ 
public : 
    enum flags 
    { 
     IS_STRING, 
     IS_EMPTY, 
     HAS_GOT_COPIED, 

     MARKER 
    }; 

private: 
    void* m_value; 
    std::bitset<MARKER> m_flags; 

public: 
    ..... 
    Atom(Atom& atm) 
    { 
     atm.m_flags.set(HAS_GOT_COPIED); 
     ..... 
    } 
    ..... 
    ~Atom() 
    { 
     if(m_flags.test(IS_STRING) && !m_flags.test(HAS_GOT_COPIED)) 
     { 
      std::string* val = static_cast<std::string*>(m_value); 
      delete val; 
     } 
    } 
}; 

这是一个很好的方法,以找出是否有没有更多提及的std :: string *?任何意见..

我看过boost :: any和poco :: DynamicAny。由于我需要序列化,我不能使用这些。

谢谢, Gokul。

+1

你看过boost :: variant吗?序列化如何影响boost :: any的使用? (我从来没有尝试过poco :: DynamicAny) – 2010-03-31 19:42:59

+1

为什么模板上的Atom对象会包含对象的类型? – 2010-03-31 19:43:09

+0

@George:这不会是一种数据类型,并不符合目的。 – Gokul 2010-03-31 20:08:27

回答

4

这种方法的一个主要缺陷是,你确实需要一个引用计数,而不是一个位“已被复制”的标志。如果您多次复制字符串,该位将不起作用。由于写的,你会惹上麻烦,如果你创建一个Atom的副本,之前的原始删除副本:

Atom a("hello world"); 

if (...) { 
    Atom b(a); 
    // b is destroyed, deleting the string 
} 

// Uh oh, the string's been deleted but a is still referencing it. 
cout << (string) a; 

我也不会重新发明轮子。如果boost::any无法正常工作,您仍然可以在内部使用它来代替m_value字段,以存储Atom类的数据。这将为您处理所有的构建/复制/销毁细节。

+0

谢谢..我得到了问题。但是我无法使用boost :: any,因为它不支持boost序列化 – Gokul 2010-03-31 19:44:12

+1

您可以将序列化添加到您的类中(如您现在所做的那样)并在内部使用boost :: any或boost :: variant – 2010-03-31 19:54:44

+0

@David :我不想支付boost :: any的代价,如果我无法存储type_info(通过将所有内容转换为void *然后将其放入boost :: any中)。目前,我正在通过将数据作为字节流与长度进行序列化。 – Gokul 2010-03-31 20:02:01

4

我想你应该考虑使用boost :: shared_ptr(或std :: tr1 :: shared_ptr)的可能性。

+0

这是一个按值传递数据类型。我认为你的建议对通过引用数据类型是有效的。 – Gokul 2010-03-31 19:30:25

+0

他的建议对于可复制的按价值传递课程非常有用。显然,不可复制的按引用类型没有复制问题。 – 2010-03-31 19:34:22

+1

我打算使用shared_ptr来跟踪std :: string *并在正确的时刻释放。你的代码如何处理一个包含std :: string的Atom已被多次拷贝并且原始实例的生命周期最长的情况? – 2010-03-31 19:35:32

3

您可能想将“写入时复制”输入到Google并阅读相关主题。它是如何实现的,它用于什么,它的缺点是什么。

你有看过吗boost::any

+0

是的,我看着boost :: any。它不能在这里使用,因为我们需要序列化这个。 – Gokul 2010-03-31 19:31:42

+0

@Gokul:这不像你的类型是免费的序列化 - 你也必须自己实现。如果你将自己建立在“提升:任何”基础上,至少你有一个坚实的基础。 – sbi 2010-04-01 10:24:41

1

除了这种'通用数据类型'是否是一个好主意,如果你不复制字符串,这个类可以确定它拥有它指向的字符串吗?你能保证只有通过new分配的字符串才会被传递给班级以获得所有权吗?

这个类的设计看起来好像有问题。

+0

是的,我将只有该构造函数和set语句。 – Gokul 2010-03-31 19:32:49

+0

@Gokul - 这不是真正的问题。你能否确定调用构造函数的人只能使用通过'new'分配的字符串并且调用者不会随后调用字符串中的'delete'?这些规则很难在您的设计中实施,所以在进行这样的设计之前先考虑它们可能是一个好主意。 – 2010-03-31 19:50:09

+0

对不起,我没有提到它,但人们只会将它作为std :: string传递,我将它转换成std :: string *在这里面。所以我需要释放它。如果它作为std :: string *传递,那么这不会担心释放它。 – Gokul 2010-03-31 19:59:08

2

我第一份工作的第一项任务就是设计一个变体类。你可以在这里找到一些基本的代码(和讨论)在comp.lang.c++.moderated post

由于您还需要序列化,因此您可能对JsonCpp库感兴趣。我认为它只是提供你正在寻找的东西:一个数据类型,可以是一个字符串,布尔值,整数,数组,对象等...(Json::Value类)。

+0

谢谢!我会看看。 – Gokul 2010-03-31 19:41:58

+0

陌生人,请解释当你downvoting :) – StackedCrooked 2010-03-31 20:46:06