2

我正在将消息类的当前实现从以下位置更改:

class Message
{
public:
    Message(uint8* buffer, uint8 length) : m_contents(buffer), m_length(length) { }

    uint8 getLength() const {return m_length; }
    const uint8* getData() const { return m_contents; }
protected:
    uint8* m_contents;
    uint8 m_length;
};

在构造函数中只取长度,在构造函数中动态分配,在析构函数中删除。

我认为它应该看起来像:

Message(uint8 length) : m_length(length)
{
    m_contents = new uint8[length];
}

~Message() 
{
    delete [] m_contents;
    m_contents = NULL;
}

附加信息:消息对象将被传递给将其发送出去的串行端口对象。它还将被子类化为多个 CustomMessage 类。

我的问题是:在这个简单的例子中,是否有任何理由使用某种类型的智能指针?一个例子会很有帮助。谢谢!

4

2 回答 2

2

有什么理由使用某种类型的智能指针吗?

其实这取决于。考虑这段代码:

 Message m1 (1024);
 Message m2 (m1);

你想m2 成为一个深拷贝m1吗?你想要m1m2共享内存的底层缓冲区吗?或者您不希望副本以(深或其他)开头?也就是说,第二条语句应该会导致编译错误?

  • 如果您希望他们共享内存,那么是的,您应该使用std::shared_ptr.
  • 如果您希望它们在内存中是完全不同的副本(深拷贝),那么不,您不应该使用shared_ptr; 你可以使用std::unique_ptr,但你也必须实现复制语义。但是,如果您使用这种情况,那么最好使用std::vector<uint8>而不是实现自己的类:

    typedef std::vector<uint8> Message;
    
    Message m1(1024);
    Message m2(m1); //m2 is a deep-copy of m1
    
  • 如果您想防止复制,因此第二条语句会导致编译错误,那么您必须通过=deleteing它们禁用复制语义:

    Message(Message const &) = delete;
    Message& operator=(Message const &) = delete;
    

    请注意,在这种情况下,您必须自己实现移动语义。移动通常是有道理的,所以我不会对此发表评论。

希望有帮助。

于 2013-01-30T18:06:05.387 回答
1

关于复制和分配的政策是什么。如果您使类不可复制,则使用智能指针没有真正的优势。如果您支持深拷贝,我认为没有标准的智能指针可以完成这项工作;您必须自己实施复制和分配。或使用 std::vector<char>,它将为您完成所有这些。如果您支持浅拷贝,那么std::shared_ptr非常适合这项工作。

如果类在构造后是不可变的(如果你已经显示了所有成员),浅拷贝或无拷贝是要走的路。坦率地说,我可能只是在这里使用std::stringor std::vector而不用担心它。它默认提供深拷贝,这可能有点矫枉过正,但它肯定是最简单的解决方案。

于 2013-01-30T18:13:07.477 回答