草庐IT

C++11 make_shared 实例化

coder 2023-11-17 原文

很抱歉这个问题太长了,但一些上下文是必要的。我有一些代码似乎对我正在从事的项目很有用:

class Foo
{
public:
    Foo( int bar = 1 );
    ~Foo();
    typedef std::shared_ptr< Foo > pointer_type;
    static pointer_type make( int bar = 1 )
    {
        return std::make_shared< Foo >( bar );
    }

...
}

如您所见,它提供了一种将任何类构造为 PointerType 的直接方法,该类将 shared_ptr 封装到该类型:

auto oneFoo = Foo::make( 2 );

因此,您无需在整个代码库中引用 make_shared 和 shared_ptr 即可获得 shared_ptr 的优势。

在类中封装智能指针类型有几个优点:

  1. 它让您可以控制指针类型的可复制性和可移动性。
  2. 它向调用者隐藏了 shared_ptr 的详细信息,因此可以在 Instance() 调用中放置重要的对象构造,例如那些抛出异常的构造。
  3. 在处理使用多个智能指针实现的项目时,您可以更改底层智能指针类型。您可以切换到 unique_ptr 或什至切换到特定类的原始指针,调用代码将保持不变。
  4. 它将有关(智能)指针构造和别名的详细信息集中在最了解如何操作的类中。
  5. 它让您决定哪些类可以使用智能指针以及哪些类必须在堆栈上构建。 PointerType 字段的存在向调用者提供了有关可以创建与该类对应的指针类型的提示。如果没有为类定义 PointerType,则表明不能创建指向该类的指针;因此,必须在堆栈上创建该特定类,RAII 样式。

但是,如果不直接键入必需的 typedef 和静态 PointerType Instance() 函数,我看不出有什么明显的方法可以将这段代码应用于我项目中的所有类。我怀疑应该有一些一致的、C++11 标准的、跨平台的方法来使用基于策略的模板来做到这一点,但是一些实验还没有找到一种明显的方法来将这个平凡地应用到一个类中的一堆类中。在所有现代 C++ 编译器上进行干净编译的方式。

您能想出一种优雅的方式来将这些概念添加到一堆类中,而无需进行大量剪切和粘贴吗?一个理想的解决方案会在概念上限制可以为哪些类型的类创建哪些类型的指针(一个类使用 shared_ptr 而另一个使用原始指针),并且它还将通过其自己的首选方法处理任何受支持类型的实例化。这样的解决方案甚至可以通过在编译时适本地失败来处理和/或限制非标准和标准智能和哑指针类型之间的强制转换。

最佳答案

一种方法是使用 curiously recurring template pattern .

template<typename T>
struct shared_factory
{
    using pointer_type = std::shared_ptr<T>;

    template<typename... Args>
    static pointer_type make(Args&&... args)
    {
        return std::make_shared<T>(std::forward<Args>(args)...);
    }
};

struct foo : public shared_factory<foo>
{
    foo(char const*, int) {}
};

我相信这会给你你想要的。

foo::pointer_type f = foo::make("hello, world", 42);

然而...

我不推荐使用这种方法。试图规定类型的用户如何实例化该类型是不必要的限制。如果他们需要一个 std::shared_ptr,他们可以创建一个。如果他们需要 std::unique_ptr,他们可以创建一个。如果他们想在堆栈上创建一个对象,他们可以。我认为强制要求如何创建和管理用户的对象不会有任何好处。

解决您的问题:

  1. It lets you control the copyability and moveability of the pointer types.

这有什么好处?

  1. It hides the shared_ptr details from callers, so that non-trivial object constructions, such as those that throw exceptions, can be placed within the Instance() call.

我不确定你在这里的意思。希望您不会捕获异常并返回 nullptr。那将是 Java 级的错误。

  1. You can change the underlying smart pointer type when you're working with projects that use multiple smart pointer implementations. You could switch to a unique_ptr or even to raw pointers for a particular class, and calling code would remain the same.

如果您正在使用多种智能指针,或许让用户根据给定情况选择合适的种类会更好。此外,我认为具有相同的调用代码但返回不同类型的句柄可能会造成混淆。

  1. It concentrates the details about (smart) pointer construction and aliasing within the class that knows most about how to do it.

一个类在什么意义上“最”了解如何进行指针构造和别名?

  1. It lets you decide which classes can use smart pointers and which classes must be constructed on the stack. The existence of the PointerType field provides a hint to callers about what types of pointers can be created that correspond for the class. If there is no PointerType defined for a class, this would indicate that no pointers to that class may be created; therefore that particular class must be created on the stack, RAII style.

同样,我从根本上不同意某种类型的对象必须以某种方式创建和管理的想法。这是 singleton pattern 的原因之一。太阴险了。

关于C++11 make_shared 实例化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35953783/

有关C++11 make_shared 实例化的更多相关文章

  1. ruby-on-rails - rails : keeping DRY with ActiveRecord models that share similar complex attributes - 2

    这似乎应该有一个直截了当的答案,但在Google上花了很多时间,所以我找不到它。这可能是缺少正确关键字的情况。在我的RoR应用程序中,我有几个模型共享一种特定类型的字符串属性,该属性具有特殊验证和其他功能。我能想到的最接近的类似示例是表示URL的字符串。这会导致模型中出现大量重复(甚至单元测试中会出现更多重复),但我不确定如何让它更DRY。我能想到几个可能的方向...按照“validates_url_format_of”插件,但这只会让验证干给这个特殊的字符串它自己的模型,但这看起来很像重溶液为这个特殊的字符串创建一个ruby​​类,但是我如何得到ActiveRecord关联这个类模型

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

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

  3. ruby-on-rails - 如何使用 instance_variable_set 正确设置实例变量? - 2

    我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击

  4. ruby 正则表达式 - 如何替换字符串中匹配项的第 n 个实例 - 2

    在我的应用程序中,我需要能够找到所有数字子字符串,然后扫描每个子字符串,找到第一个匹配范围(例如5到15之间)的子字符串,并将该实例替换为另一个字符串“X”。我的测试字符串s="1foo100bar10gee1"我的初始模式是1个或多个数字的任何字符串,例如,re=Regexp.new(/\d+/)matches=s.scan(re)给出["1","100","10","1"]如果我想用“X”替换第N个匹配项,并且只替换第N个匹配项,我该怎么做?例如,如果我想替换第三个匹配项“10”(匹配项[2]),我不能只说s[matches[2]]="X"因为它做了两次替换“1fooX0barXg

  5. ruby-on-rails - rails : How to make a form post to another controller action - 2

    我知道您通常应该在Rails中使用新建/创建和编辑/更新之间的链接,但我有一个情况需要其他东西。无论如何我可以实现同样的连接吗?我有一个模型表单,我希望它发布数据(类似于新View如何发布到创建操作)。这是我的表格prohibitedthisjobfrombeingsaved: 最佳答案 使用:url选项。=form_for@job,:url=>company_path,:html=>{:method=>:post/:put} 关于ruby-on-rails-rails:Howtomak

  6. ruby-on-rails - Rails - 从另一个模型中创建一个模型的实例 - 2

    我有一个正在构建的应用程序,我需要一个模型来创建另一个模型的实例。我希望每辆车都有4个轮胎。汽车模型classCar轮胎模型classTire但是,在make_tires内部有一个错误,如果我为Tire尝试它,则没有用于创建或新建的activerecord方法。当我检查轮胎时,它没有这些方法。我该如何补救?错误是这样的:未定义的方法'create'forActiveRecord::AttributeMethods::Serialization::Tire::Module我测试了两个环境:测试和开发,它们都因相同的错误而失败。 最佳答案

  7. ruby-on-rails - RSpec:避免使用允许接收的任何实例 - 2

    我正在处理旧代码的一部分。beforedoallow_any_instance_of(SportRateManager).toreceive(:create).and_return(true)endRubocop错误如下:Avoidstubbingusing'allow_any_instance_of'我读到了RuboCop::RSpec:AnyInstance我试着像下面那样改变它。由此beforedoallow_any_instance_of(SportRateManager).toreceive(:create).and_return(true)end对此:let(:sport_

  8. ruby-on-rails - 使用 ruby​​ 将多个实例变量转换为散列的更好方法? - 2

    我收到格式为的回复#我需要将其转换为哈希值(针对活跃商家)。目前我正在遍历变量并执行此操作:response.instance_variables.eachdo|r|my_hash.merge!(r.to_s.delete("@").intern=>response.instance_eval(r.to_s.delete("@")))end这有效,它将生成{:first="charlie",:last=>"kelly"},但它似乎有点hacky和不稳定。有更好的方法吗?编辑:我刚刚意识到我可以使用instance_variable_get作为该等式的第二部分,但这仍然是主要问题。

  9. ruby-on-rails - 如何重构 "shared"方法? - 2

    我正在使用RubyonRails3.2.2,我想从我的模型/类中“提取”一些方法。也就是说,在不止一个类/模型中,我有一些方法(注意:方法与用户授权相关,并被命名为“CRUD方式”),这些方法实际上是相同的;所以我认为DRY方法是将这些方法放在“共享”模块或类似的东西中。实现该目标的常见且正确的方法是什么?例如,我应该将“共享”代码放在哪里(在哪些目录和文件中)?如何在我的类/模型中包含提到的方法?你有什么建议?注意:我正在寻找“RubyonRails制作东西的方式”。 最佳答案 一种流行的方法是使用ActiveSupport关注点

  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.你能做的最好的事情是:

随机推荐