标签: make-shared

初始化shared_ptr成员变量,new vs make_shared?

初始化shared_ptr成员变量时:

// .h
class Customer
{
public:
  Customer();

private:
  std::shared_ptr<OtherClass> something_;
}

// .cpp
Customer():
  something_(new OtherClass())
{
}
Run Code Online (Sandbox Code Playgroud)

Customer():
  something_(std::make_shared<OtherClass>())
{
}
Run Code Online (Sandbox Code Playgroud)

是否允许使用make_shared版本?我似乎总是看到第一个版本,这是首选?

c++ initializer shared-ptr make-shared c++11

6
推荐指数
2
解决办法
1万
查看次数

new和make_shared用于共享指针

我发现了这篇文章,其中一个答案是@kerek SB说的

std::shared_ptr<Object> p1 = std::make_shared<Object>("foo");
std::shared_ptr<Object> p2(new Object("foo"));
Run Code Online (Sandbox Code Playgroud)

在你的代码中,第二个变量只是一个裸指针,而不是一个共享指针.

现在就肉了.make_shared(实际上)更有效,因为它在一个动态分配中将引用控制块与实际对象一起分配.相比之下,采用裸对象指针的shared_ptr的构造函数必须为引用计数分配另一个动态变量.权衡是make_shared(或其表兄allocate_shared)不允许您指定自定义删除器,因为分配是由分配器执行的.

(这不会影响对象本身的构造.从Object的角度来看,两个版本之间没有区别.更有效的是共享指针本身,而不是托管对象.)

现在我对这篇文章有两个问题,如果有人能澄清一下,我会很感激

  1. 为什么第二个不是共享指针?这不会增加引用计数

  2. make_shared如何只进行一次内存分配,而new将两次内存分配,从而使make_shared更有效率?

对此有点澄清将不胜感激.

c++ pointers shared-ptr make-shared

6
推荐指数
2
解决办法
3050
查看次数

处理数组时 make_unique 和 make_shared 之间的差异

从 C++17 开始,您可以使用它make_unique来创建指向数组的智能指针,例如:

unique_ptr<int[]> ptr = make_unique<int[]>(10);
Run Code Online (Sandbox Code Playgroud)

这将创建一个指向 10 个元素的数组的智能指针(事实上,将调用正确的 deleter[] 也很棒)。

然而,根据this make_shared不支持这样的功能(至少在 C++17 中不支持,据我所知):

shared_ptr<int[]> ptr = make_shared<int[]>(10);
Run Code Online (Sandbox Code Playgroud)

上面的代码显然是非法的。事实上,我的 Visual Studio 2017 (v141) 吐出了以下错误:

C2070: 'int[]': illegal sizeof operand'
Run Code Online (Sandbox Code Playgroud)

有趣的是,shared_ptr它本身确实支持数组类型(即shared_ptr<int[]>合法,但make_shared又不支持。然而make_unique确实如此。

问题是,是什么阻止了标准制定者支持make_shared数组类型,就像 的情况一样make_unique

c++ smart-pointers make-shared

6
推荐指数
1
解决办法
6009
查看次数

将make_shared与受保护的构造函数+抽象接口一起使用

给定一个抽象接口和从该接口派生的实现,其中构造函数受到保护(这些对象的创建只能从类工厂中获得 - 实现DI模式),如何在工厂函数中使用make_shared?

例如:

class IInterface
{    
public:    
    virtual void Method() = 0;
};

class InterfaceImpl : public IInterface
{
public:
    virtual void Method() {}

protected:    
    InterfaceImpl() {}    
};

std::shared_ptr<IInterface> Create()
{
    std::shared_ptr<IInterface> object = std:: make_shared<InterfaceImpl>();    
    return object;
}
Run Code Online (Sandbox Code Playgroud)

make_shared显然无法访问InterfaceImpl中的受保护构造函数,或者实际上是在IInterface中,给出了以下错误


error C2248: 'InterfaceImpl::InterfaceImpl' : cannot access protected member declared in class 'InterfaceImpl'
Run Code Online (Sandbox Code Playgroud)

所以在这里阅读(问题:如何使boost :: make_shared成为我班级的朋友),我尝试将以下内容放入实现类中:


friend std::shared_ptr<InterfaceImpl> std::make_shared<InterfaceImpl>();
Run Code Online (Sandbox Code Playgroud)

它仍然无法编译.那么我也将另一个放入IInterface类.仍然没有快乐.我在这做错了什么?

编辑:用于编译的完整源文件,与"朋友"...

#include <memory>

class IInterface
{    
public:    
    friend std::shared_ptr&lt;IInterface> Create();     
    virtual void Method() = 0;
};

class …
Run Code Online (Sandbox Code Playgroud)

c++ constructor protected visual-c++-2010 make-shared

5
推荐指数
1
解决办法
6546
查看次数

C++ make_shared不可用

虽然我std::tr1::shared_ptr<T>在我的编译器中可用,但我没有make_shared.

有人能指点我正确实施make_shared吗?我看到我需要使用varargs为T的构造函数提供参数.

但是我的编译器中也没有可用的变量模板.

c++ tr1 make-shared

5
推荐指数
1
解决办法
2989
查看次数

C++为类模板提供初始化列表构造函数

我有一个带有模板参数T的类模板Templ,而Templ类有一个类型为T的数据成员,称为obj.我编写了一个可变参数构造函数模板,它将参数转发给obj的构造函数:

template <class T>
class Templ
{
public:
     template <class... Args> explicit Templ (Args&&... args)
     : obj (std::forward<Args>(args)...)
     {
     }
private:
     T obj;
};
Run Code Online (Sandbox Code Playgroud)

现在我意识到类型T可能是一个带有init-list构造函数的类,我希望它可以通过Templ访问.所以我检查了什么std::list::emplace,std::make_shared做了什么.它们具有像我一样的可变函数,但它们没有覆盖init-list的覆盖.由于某些原因.

所以第一个问题:为什么?我的意思是,如果我使用一个带有init-list ctor的类T,然后我用std::list<T>?为什么list ::\templates没有带初始化列表的版本?也许有一个很好的理由我应该这样做...所以我想知道.

此外,无论STL做什么 - 我应该提供一个init-list ctor作为好的设计吗?我的意思是,它就像可变的ctor,对吗?允许用户选择任何类型或种类的T,带TEMPL <>使用,并且直接调用为T.定义的任何构造函数即使它是一个构造函数采取一个init-列表.

c++ initializer-list make-shared variadic-templates c++11

5
推荐指数
1
解决办法
2533
查看次数

如何创建boost phoenix make_shared?

有可能创建boost phoenix lazy变种std::make_shared吗?我的意思是,做一些类似的事情

namespace p = boost::phoenix;
...
expr = custom_parser[_a=p::make_shared<Node>(_1,_2,_3)] >> ...
Run Code Online (Sandbox Code Playgroud)

BOOST_PHOENIX_ADAPT_FUNCTION由于可变模板的性质,人们无法使用std::make_shared.所以,如果有可能写一个包装器,那么包装器应该是variadic模板本身.

c++ boost boost-phoenix make-shared

5
推荐指数
1
解决办法
380
查看次数

尝试执行shared_ptr swap()的奇怪错误

我是一个相对的C++新手,试图将现有项目从原始指针转换为使用复杂的内存管理协议,再转换为使用C++ 11 shared_ptr.总的来说它非常顺利,我我理解shared_ptr移动语义,右值引用等方面是如何工作的.好东西.

但是,我遇到了一个奇怪的错误,我不明白,也不知道如何修复.先是一点背景.我有一个类层次结构,它以一个名为的抽象基类为根EidosValue,而一个名为EidosValue_Int_vector(间接)的类是它的具体子类:

class EidosValue
class EidosValue_Int : public EidosValue
class EidosValue_Int_vector : public EidosValue_Int
Run Code Online (Sandbox Code Playgroud)

我的代码通常是流量EidosValue,但有时,特别是在创建新值时,我需要处理特定的子类.

shared_ptr为这些类做了s的typedef ,所以我有:

typedef std::shared_ptr<EidosValue> EidosValue_SP;
typedef std::shared_ptr<EidosValue_Int_vector> EidosValue_Int_vector_SP;
Run Code Online (Sandbox Code Playgroud)

等等.好的,所以现在问题的核心.我有一个函数返回EidosValue_SP它创建的.根据函数中的逻辑,它可能会创建几个不同的具体子类之一EidosValue.所以我这样做:

EidosValue_SP MyClass::MyMethod(...)
{
    EidosValue_SP result;

    if (...)
    {
        EidosValue_Int_vector_SP int_result_SP = make_shared<EidosValue_Int_vector>();
        ... do subclass-specific stuff with int_result_SP...
        result.swap(int_result_SP);
    }
    else (...)
    {
        ...similar logic for other subclasses...
    }

    ...other shared logic...
    return result;
}
Run Code Online (Sandbox Code Playgroud)

问题出在swap() …

c++ swap shared-ptr make-shared c++11

5
推荐指数
2
解决办法
376
查看次数

如何修复"无效读取大小为8 - 40字节的块大小64空闲"

m_PhyToBtMap中SPacket中的shared_ptr似乎导致"大小为64的块内无效读取大小为8 - 40个字节".注意:在valgrind(下面的日志)发出此错误消息之前,这已经运行了近22个小时,有数百万条消息,但我也在EraseAcknowledgedPackets(下面)中遇到SIGSEGV崩溃,并怀疑这是原因.我使用的是Boost 1.63,因为交叉编译器不支持shared_ptr.在valgrind日志中调出SendMessageToBt(大小为8的无效读取)和EraseAcknowledgedPackets(大小为64的块中的40个字节).

  • 我不正确地使用shared_ptr或make_shared?
  • 在执行map.erase或insert之前是否需要添加任何检查?
  • 我能正确理解valgrind日志吗?

SPacket和m_PhyToBtMap

typedef struct SPacket
{
    boost::shared_ptr<uint8_t[]> data;
    size_t size;
} SPacket;
map<uint16_t, SPacket> m_PhyToBtMap;
Run Code Online (Sandbox Code Playgroud)

SendMessageToBt

void RadioManager::SendMessageToBt(uint8_t * response, size_t responseSize)
{
    CSrProtected ThreadSafe(m_LockPhyToBt);
    SPacket sentPacket;
    sentPacket.size = MESSAGE_HEADER_OFFSET + responseSize + CRC32_SIZE;
    sentPacket.data = boost::make_shared<uint8_t[]>(sentPacket.size);
    assert(sentPacket.data.get());
    memcpy(&sentPacket.data.get()[MESSAGE_HEADER_OFFSET], response, responseSize);
    m_AcknowledgementNumberSent = m_NextReceiveSequenceNumber;
    m_SequenceNumberSent = m_NextSendSequenceNumber;
    ++m_NextSendSequenceNumber;
    if (0 == m_NextSendSequenceNumber) m_NextSendSequenceNumber = SEQUENCE_NUMBER_MIN;
    m_PhyToBtMap[m_SequenceNumberSent] = sentPacket; // RadioManager.cpp:246
    sentPacket.data.get()[DATAGRAM_ACKNOWLEDGEMENT_LSB] = m_AcknowledgementNumberSent;
    sentPacket.data.get()[DATAGRAM_ACKNOWLEDGEMENT_MSB] = m_AcknowledgementNumberSent >> 8;
    sentPacket.data.get()[DATAGRAM_HEADER_SIZE + SEQUENCE_NUMBER_LIST_SIZE_LSB] = m_SequenceNumberSent;
    sentPacket.data.get()[DATAGRAM_HEADER_SIZE …
Run Code Online (Sandbox Code Playgroud)

c++ boost dictionary shared-ptr make-shared

5
推荐指数
1
解决办法
534
查看次数

函数 std::make_shared&lt;vector&gt; 的参数太多

我错过了一些东西std::make_shared。它不能解决 a 的类型std::initializer_list,还是我做错了什么?

#include <vector>
#include <memory>

class A {};

int main()
{
    A a;
    std::vector<A> veca{A(), A{}, a}; // this works ofc
    std::vector<A> vecb({A(), A{}, a}); // this too

    std::make_shared<std::vector<A>>(vecb); // and this, ofc
    std::make_shared<std::vector<A>>({a}); // what's wrong here?
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

错误:

main.cpp:21:41: error: too many arguments to function ‘std::shared_ptr<_Tp1> std::make_shared(_Args&& ...) [with _Tp = std::vector; _Args = {}]’
     std::make_shared<std::vector<A>>({a});
                                         ^
In file included from /usr/include/c++/6/memory:82:0,
                 from main.cpp:10:
/usr/include/c++/6/bits/shared_ptr.h:632:5: note: declared here
     make_shared(_Args&&... __args) …
Run Code Online (Sandbox Code Playgroud)

c++ vector initializer-list make-shared list-initialization

5
推荐指数
1
解决办法
901
查看次数