C ++ 11类与字符串和shared_ptr的联合 [英] C++11 class with union of string and shared_ptr

查看:492
本文介绍了C ++ 11类与字符串和shared_ptr的联合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

(这有点类似于此问题,以及灵感来源于联盟的C ++ 11常见问题解答,但不完全如此。 。)

(this is a bit similar to this question, and inspired by the C++11 FAQ on union but not exactly so...)

在语法C ++中编译类似Scheme的解释器的上下文11让我们假设我想要一个标记的联合的字符串,一个int和一些闭包。所以我可能会编码:

In the context of coding a Scheme-like interpreter in idiomatic C++11 Let's suppose I want a tagged union of a string, an int, and some closure. So I would probably code:

#include <string>
#include <new>
#include <memory>
#include <functional>
enum kind { nothing, string, integer, closure };

class Value {
 enum kind k;
 typedef std::string string_t;
  union {
    std::string str;
    int num;
    std::shared_ptr<std::function<Value(std::vector<Value>)>> clos;
  };
public:
 Value (const Value &v) 
 : k(none) {
   switch (v.k) {
   case none: break;
   case string: new(&str)string_t(v.str); break;
   case integer: num = v.num; break; 
   /// what about closure-s?
   }
   k = v.k;
 };
 Value& operator = (const Value&v) {
   switch (v.k) {
    case none: break;
    case string: new(&str)string_t(v.str); break;
    case integer: num = v.num; break; 
    /// what about closure-s?
   }
  k = v.k;
 }
 /// etc...
};

现在 closure 对于复制构造函数和赋值运算符,我很想编写代码:

Now what about the closure case? For the copy constructor and the assignment operator, I am tempted to code:

 case closure: clos = v.clos; break;

但也许我应该使用 new shared_ptr

我不想使用Boost(或任何非标准的C ++ 11库)

I don't want to use Boost (or any non standard C++11 library) for that purpose.

推荐答案

我没有看到任何理由不使用placement new std :: shared_ptr ,就像对 std :: string 所做的一样。只需指定

I don't see any reason not to use placement new for the std::shared_ptr just as you did for the std::string. Simply assigning a value as in

clos = v.clos;

不安全,因为它会调用 std的副本赋值运算符: :shared_ptr 用一个这个指针指向垃圾内存。

is not safe as it will call the copy-assignment operator of std::shared_ptr with a this pointer that potentially points to garbage memory. It might try to delete something that isn't there.

同样,在您的副本赋值运算符中,您可以使用应该在你放置新对象之前销毁旧对象或旧值将泄露。

Likewise, in your copy-assignment operator, you should destroy the old object before you emplace the new one or the old value will leak.

using std::string;
using std::shared_ptr;
if (&v == this)
  return *this;  // self-assignment
switch (this->k)
  {
  case string:
    this->str.~string();
    break;
  case closure:
    this->clos.~shared_ptr();
    break;
  }
this->k = nothing;
// Now we are ready to take the new value.

如果您使用copy& swap 成语。因为我没有看到没有使用它的任何明显的性能增益,我不认为这将花费你额外的这里。

The code will probably become easier to maintain if you use the copy & swap idiom. Since I don't see any obvious performance gains of not using it, I don't think it will cost you anything extra here.

这篇关于C ++ 11类与字符串和shared_ptr的联合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆