草庐IT

c++ - 持有大量共享状态的访问者类 : best way to implement reference semantics?

coder 2024-02-22 原文

这个问题大致基于使用 Visitor 的 Boost.Graph 库 (BGL) -like 模式来定制递归(搜索)算法。 BGL 按值传递访问者对象(类似于 STL 函数对象)和 documentation

Since the visitor parameter is passed by value, if your visitor contains state then any changes to the state during the algorithm will be made to a copy of the visitor object, not the visitor object passed in. Therefore you may want the visitor to hold this state by pointer or reference.

我的问题:实现有状态访问者类的引用语义的最佳方式是什么?从精确的指针类(原始与唯一与共享,常量与非常量)中抽象出来,放置引用的最佳位置是什么:在参数传递中还是在数据成员中?

备选方案 1:访问者通过指针保存状态,并按值传递(如在 Boost.Graph 中)

class Visitor
{
public:
    Visitor(): state_(new State()) {}
    void start() { /* bla */ }
    void finish() { /* mwa */ }
private:
    State* state_;
}

template<typename Node, typename Visitor>
int algorithm(Node const& n, Visitor v)
{
    v.start();
    algorithm(next(n), v);
    v.finish();
}

方案2:访问者按值保存数据,并通过指针传递

class Visitor
{
public:
    Visitor(): state_() {}
    void start() { /* bla */ } 
    void finish() { /* mwa */ }
private:
    State state_;
}

template<typename Node, typename Visitor>
int algorithm(Node const& n, Visitor* v)
{
    v->start();
    algorithm(next(n), v);
    v->finish();
}

我目前的倾向: 我发现备选方案 1 [按持有指针/引用的对象的值传递] 有点不舒服,因为访问者不满足值语义,所以我宁愿引用参数列表[备选方案 2] 中的语义清晰。是否有任何其他相关注意事项或备选方案?

最佳答案

还有第三种选择:

class Visitor
{
public:
    Visitor(): state_() {}
    void start() { /* bla */ } 
    void finish() { /* mwa */ }
private:
    State state_;
};

template<typename Node, typename Visitor>
int algorithm(Node const& n, Visitor v)
{
    v.start();
    algorithm(next(n), v);
    v.finish();
}

// Set the reference semantics here, use value everywhere else
algorithm(myNode, boost::ref(myVisitor)); // ... or std::ref in c++11

我认为这通常受到标准的青睐,而不是明确地将某物标记为指针或引用。毕竟,std::refstd::cref已经被引入来解决这个问题。

另一方面,在“C++ 编码标准”一书中,Sutter 和 Alexandrescu 认为仿函数应该始终易于复制且快速。他们建议在内部使用引用计数状态 block (IIRC,这里没有这本书)。所以虽然 std::refstd::cref会解决你的问题,它们更常用于“适应”非仿函数对象,例如通过 std::vector 时通过std::bind .

备选方案 1,带有 shared_ptr<T> (或更好:shared_ptr<T const>)可能是您的最佳选择。在任何一种情况下,您都只是将指针语义“包装”在 BGL 代码的值语义后面,只要您正确设置所有对象生命周期就可以。

关于c++ - 持有大量共享状态的访问者类 : best way to implement reference semantics?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14440501/

有关c++ - 持有大量共享状态的访问者类 : best way to implement reference semantics?的更多相关文章

  1. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  2. ruby - 在 Ruby 程序执行时阻止 Windows 7 PC 进入休眠状态 - 2

    我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0

  3. ruby-on-rails - 在混合/模块中覆盖模型的属性访问器 - 2

    我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah

  4. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  5. ruby - 续集在添加关联时访问many_to_many连接表 - 2

    我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以

  6. ruby - 通过 ruby​​ 进程共享变量 - 2

    我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是

  7. ruby-on-rails - 跳过状态机方法的所有验证 - 2

    当我的预订模型通过rake任务在状态机上转换时,我试图找出如何跳过对ActiveRecord对象的特定实例的验证。我想在reservation.close时跳过所有验证!叫做。希望调用reservation.close!(:validate=>false)之类的东西。仅供引用,我们正在使用https://github.com/pluginaweek/state_machine用于状态机。这是我的预订模型的示例。classReservation["requested","negotiating","approved"])}state_machine:initial=>'requested

  8. ruby - 字符串文字中的转义状态作为 `String#tr` 的参数 - 2

    对于作为String#tr参数的单引号字符串文字中反斜杠的转义状态,我觉得有些神秘。你能解释一下下面三个例子之间的对比吗?我特别不明白第二个。为了避免复杂化,我在这里使用了'd',在双引号中转义时不会改变含义("\d"="d")。'\\'.tr('\\','x')#=>"x"'\\'.tr('\\d','x')#=>"\\"'\\'.tr('\\\d','x')#=>"x" 最佳答案 在tr中转义tr的第一个参数非常类似于正则表达式中的括号字符分组。您可以在表达式的开头使用^来否定匹配(替换任何不匹配的内容)并使用例如a-f来匹配一

  9. ruby - Net::HTTP 获取源代码和状态 - 2

    我目前正在使用以下方法获取页面的源代码:Net::HTTP.get(URI.parse(page.url))我还想获取HTTP状态,而无需发出第二个请求。有没有办法用另一种方法做到这一点?我一直在查看文档,但似乎找不到我要找的东西。 最佳答案 在我看来,除非您需要一些真正的低级访问或控制,否则最好使用Ruby的内置Open::URI模块:require'open-uri'io=open('http://www.example.org/')#=>#body=io.read[0,50]#=>"["200","OK"]io.base_ur

  10. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

随机推荐