English 中文(简体)
C++中共享和正常分享的吸收
原标题:Difference in make_shared and normal shared_ptr in C++
std::shared_ptr<Object> p1 = std::make_shared<Object>("foo");
std::shared_ptr<Object> p2(new Object("foo"));

我无法理解为什么<代码>make_commd<>/code>比直接使用共有_ptr更有效率。

我需要一步一步地解释双方制造的物体和作业的顺序,以便我理解<条码>make_共有<<<>>/代码>是有效的。 我举了一个例子。

最佳回答

差异是<代码>std:make_commd 履行一个席位分配,而打上std:共有_ptr<>。 施工人从事二次施工。

Where do the heap-allocations happen?

<代码>std: 共享_ptr 管理两个实体:

  • the control block (stores meta data such as ref-counts, type-erased deleter, etc)
  • the object being managed

<代码>std:make_commd就控制区和数据所必须的空间进行单一比例的核算。 在另一起案件中,new Obj ("foo”) 援引管理数据和<代码>的分行:共有-ptr的构造为控制区。

For further information, check out the implementation notes at cppreference.

Update I: Exception-Safety

<NOTE (2019/08/30): 由于职能理由评价命令的改变,C+17号文件没有出现问题。 具体来说,每项职能的理由都必须在评价其他论点之前充分加以解释。

Since the OP seem to be wondering about the exception-safety side of things, I ve updated my answer.

考虑这一实例

void F(const std::shared_ptr<Lhs> &lhs, const std::shared_ptr<Rhs> &rhs) { /* ... */ }

F(std::shared_ptr<Lhs>(new Lhs("foo")),
  std::shared_ptr<Rhs>(new Rhs("bar")));

由于C++允许任意下令对低压进行评价,因此可能下令:

  1. new Lhs("foo"))
  2. new Rhs("bar"))
  3. std::shared_ptr<Lhs>
  4. std::shared_ptr<Rhs>

现在,用第2步(例如,从记忆例外,/code>的构造者略去了某些例外)。 然后,我们失去第1步的记忆,因为没有任何机会清理它。 问题的核心是,原始点子 t已经通过到<代码>std:共有_ptr的构造。

解决这一问题的一种办法是,以单独的方式行事,这样不可能发生这种仲裁命令。

auto lhs = std::shared_ptr<Lhs>(new Lhs("foo"));
auto rhs = std::shared_ptr<Rhs>(new Rhs("bar"));
F(lhs, rhs);

The preferred way to solve this of course is to use std::make_shared instead.

F(std::make_shared<Lhs>("foo"), std::make_shared<Rhs>("bar"));

Update II: Disadvantage of std::make_shared

Quoting

Since there there s only one allocation, the pointee s memory cannot be deallocated until the control block is no longer in use. A weak_ptr can keep the control block alive indefinitely.

Why do instances of weak_ptrs keep the control block alive?

必须有<代码>weak_ptr,以确定所管理物体是否仍然有效(例如<代码>锁<>>)。 通过核对控制区储存的有管理物体的<编码>共享_ptr<>/code>号数,即可做到这一点。 结果是,控制区一直存在,直至<条码>共享_ptr<>/条码>和<条码>>> 。 页: 1

Back to std::make_shared

Since std::make_shared makes a single heap-allocation for both the control block and the managed object, there is no way to free the memory for control block and the managed object independently. We must wait until we can free both the control block and the managed object, which happens to be until there are no shared_ptrs or weak_ptrs alive.

Suppose we instead performed two heap-allocations for the control block and the managed object via new and shared_ptr constructor. Then we free the memory for the managed object (maybe earlier) when there are no shared_ptrs alive, and free the memory for the control block (maybe later) when there are no weak_ptrs alive.

问题回答

还有一种情况是,这两种可能性与前面提到的两种可能性大不相同:如果你需要称作非公共建筑商(受保护或私人),则可能无法分享,而新工程罚款的变数。

class A
{
public:

    A(): val(0){}

    std::shared_ptr<A> createNext(){ return std::make_shared<A>(val+1); }
    // Invalid because make_shared needs to call A(int) **internally**

    std::shared_ptr<A> createNext(){ return std::shared_ptr<A>(new A(val+1)); }
    // Works fine because A(int) is called explicitly

private:

    int val;

    A(int v): val(v){}
};

共同点人既管理对象本身,又管理一个小物体,其中包含参考数据和其他保存数据。 <代码>make_commd可分配一组记忆,以保存其中的两部分;从点到已分配的物体建造一个共享点,将需要分配第二组,以储存参考数。

除这一效率外,使用<条码>make_共有<<<>>条/代码>,意味着你不需要处理<条码>新<>>和所有原材料,给予更好的例外安全,因此不可能在将物体分配到智能点之前作出例外规定。

如果你们需要对共同接收者控制的目标进行特别的记忆调整,那么你不能依靠共享,但我认为这只是不使用它的唯一良好理由。

www.un.org/Depts/DGACM/index_spanish.htm 1. 履行两粒分配办法

  1. Control block(reference count)
  2. Object being managed

www.un.org/Depts/DGACM/index_spanish.htm 只做一次肥皂分配

  1. Control block and object data.

我认为,红花园答案的例外安全部分仍是一个有效的关切。 当创造共同的吸收者时:共享的吸收者;T >(新T),新T可能成功,而共享的控制区分配可能失败。 在这种情形下,新分配的T将泄露,因为共享的接收器无法知道它是在当地创建的,而且可以安全地删除它。 还是我失踪了吗? 我认为,关于职能参数评价的更严格的规则在这方面没有任何帮助。

关于在分配上花费的效率和关切时间,我作了以下简单检验,我通过这两种方式(一次是时):

for (int k = 0 ; k < 30000000; ++k)
{
    // took more time than using new
    std::shared_ptr<int> foo = std::make_shared<int> (10);

    // was faster than using make_shared
    std::shared_ptr<int> foo2 = std::shared_ptr<int>(new int(10));
}

The thing is, using make_shared took the double time compared with using new. So, using new there are two heap allocations instead of one using make_shared. Maybe this is a stupid test but doesn t it show that using make_shared takes more time than using new? Of course, I m talking about time used only.





相关问题
Undefined reference

I m getting this linker error. I know a way around it, but it s bugging me because another part of the project s linking fine and it s designed almost identically. First, I have namespace LCD. Then I ...

C++ Equivalent of Tidy

Is there an equivalent to tidy for HTML code for C++? I have searched on the internet, but I find nothing but C++ wrappers for tidy, etc... I think the keyword tidy is what has me hung up. I am ...

Template Classes in C++ ... a required skill set?

I m new to C++ and am wondering how much time I should invest in learning how to implement template classes. Are they widely used in industry, or is this something I should move through quickly?

Print possible strings created from a Number

Given a 10 digit Telephone Number, we have to print all possible strings created from that. The mapping of the numbers is the one as exactly on a phone s keypad. i.e. for 1,0-> No Letter for 2->...

typedef ing STL wstring

Why is it when i do the following i get errors when relating to with wchar_t? namespace Foo { typedef std::wstring String; } Now i declare all my strings as Foo::String through out the program, ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

Window iconification status via Xlib

Is it possible to check with the means of pure X11/Xlib only whether the given window is iconified/minimized, and, if it is, how?

热门标签