我首先假设一般来说,在堆栈中分配小对象,在动态内存中分配大对象是个好主意.另一个假设是,在尝试学习内存,STL容器和智能指针时,我可能会感到困惑.

考虑下面的例子,我有一个必须通过智能指针在免费商店中分配的对象,例如,我可以依赖客户从工厂获取所述对象.此对象包含一些使用STL容器专门分配的数据,该容器恰好是std :: vector.在一种情况下,这个数据向量本身是使​​用一些智能指针动态分配的,而在另一种情况下我只是不使用智能指针.

设计A和设计B之间是否存在实际差异,如下所述?

情况A:

class SomeClass{
public:
    SomeClass(){ /* initialize some potentially big STL container */ }
private:
    std::vector<double> dataVector_;
};

情况B:

class SomeOtherClass{
public:
    SomeOtherClass() { /* initialize some potentially big STL container,but is it allocated in any different way? */ }
private:
    std::unique_ptr<std::vector<double>> pDataVector_;
};

一些工厂功能.

std::unique_ptr<SomeClass> someClassFactory(){
    return std::make_unique<SomeClass>();
}

std::unique_ptr<SomeOtherClass> someOtherClassFactory(){
    return std::make_unique<SomeOtherClass>();
}

使用案例:

int main(){
    //in my case I can reliably assume that objects themselves
    //are going to always be allocated in dynamic memory
    auto pSomeClassObject(someClassFactory());
    auto pSomeOtherClassObject(someOtherClassFactory());

    return 0;
}

我希望两种设计选择都有相同的结果,但它们呢?
选择A或B有任何优势或劣势吗?具体来说,我一般应该选择设计A,因为它更简单或有更多考虑因素吗? B在道德上是错误的,因为它可以为std :: vector悬挂吗?

tl; dr:智能指针指向STL容器是不是错了?

编辑:
相关答案指出了对我这样困惑的人有用的额外信息.
Usage of objects or pointers to objects as class members and memory allocation
和Class members that are objects – Pointers or not? C++
并且更改一些谷歌关键字会将我带到When vectors are allocated,do they use memory on the heap or the stack?

解决方法

在这里使用std :: unique_ptr只是浪费,除非你的目标是编译器防火墙(基本上将编译时依赖性隐藏到vector,但是你需要向标准容器转发声明).

你正在添加一个间接,但更重要的是,SomeClass的全部内容在访问内容时变成3个独立的内存块(SomeClass与/包含指向std :: vector的块指向其元素数组的unique_ptr的块).此外,您还需要支付额外多余的堆开销.

现在你可能开始想象一个间接对向量有帮助的场景,比如你可以在两个SomeClass实例之间浅移/交换unique_ptrs.是的,但是矢量已经提供了没有unique_ptr包装器的顶部.它已经有像空的状态,你可以重用一些有效/无效的概念.

请记住,可变大小的容器本身是小对象,而不是大对象,指向潜在的大块.矢量不大,其动态内容可以.为大对象添加间接的想法并不是一个坏的经验法则,但矢量不是一个大的对象.随着移动语义的到位,值得一提的是它更像是一个指向一个可以被浅层复制和廉价交换的大内存块.在移动语义之前,有更多的理由认为像std :: vector这样的东西是一个不可分割的大对象(尽管它的内容总是可以交换),但是现在值得把它想象成一个指向大而动态内容的小手柄.

通过unique_ptr之类的东西引入间接的一些常见原因是:

>抽象&躲了起来.如果你试图抽象或隐藏某些类型/子类型Foo的具体定义,那么这就是你需要间接的地方,这样它的句柄就可以被那些不知道的人捕获(或者甚至可能用于抽象)正是Foo是什么.
>允许一个大的,连续的1块类型对象从所有者传递给所有者,而不调用副本或使引用/指针(包括迭代器)无效到它或其内容.
>一种仓促的理由是浪费但有时候在最后期限内有用,就是简单地将有效性/无效状态引入一些本身并不存在的东西.
>偶尔,它可以作为一种优化来提升某些不常访问的,较大的对象成员,以便其常用的元素更适合(可能还有相邻的对象)在缓存行中. unique_ptr可以让你拆分该对象的内存布局,同时仍然符合RAII.

现在将shared_ptr包装在标准容器之上可能会有更多合法的应用程序,如果您有一个容器实际上可以由多个所有者(合理地)拥有.使用unique_ptr,一次只有一个所有者可以拥有该对象,标准容器已经允许您交换并移动彼此的内部内部(大的动态部分).所以我没有理由用直接用unique_ptr包装一个标准容器,因为它已经有点像一个动态数组的智能指针(但有更多的功能来处理动态数据,包括深层复制它,如果需要) .

如果我们谈论非标准容器,比如说你正在使用提供一些数据结构的第三方库,这些数据结构的内容可能会变得非常大但是它们无法提供那些廉价,无效的移动/交换语义,那么你可能表面上将它包装在unique_ptr周围,交换一些创建/访问/破坏开销,以便将这些廉价的移动/交换语义作为一种解决方法.对于标准容器,不需要这样的解决方法.

c – 对于数据成员,如果包含的对象已经在动态内存中,那么动态分配此变量(或不是)之间是否有任何区别?的更多相关文章

  1. HTML5页面无缝闪开的问题及解决方案

    这篇文章主要介绍了HTML5页面无缝闪开方案,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  2. ios – 将容器带到视图前方

    我怎样才能解决这个问题?

  3. ios – 如何使用XCode 6.4下载和替换AppGroup容器

    我知道如何使用XCode6的Devices窗口下载和替换特定iOS应用程序的文件系统容器.但是对于我正在开发的应用程序,我需要能够下载和替换共享的AppGroup容器以进行调试.这将使我能够模拟AppGroup文件夹内容中的情况以进行测试.任何人都可以告诉我如何做到这一点?

  4. ios – 在UITableView上移动UIView – 触摸顶部UIView仍然选择表行

    =======用一些代码编辑:这是我在容器B中所做的代码.这是B帧的一个非常直接的动画.self.view是ContainerB的UIView.所有视图都在屏幕上通过故事板.其他容器是B的子视图.请让我知道你想看到的其他代码.解决方法嗯……不确定这是否适用于您的情况,但尝试在容纳所有其他容器的更大容器中管理您的动画.我的意思是,创建一个包含A,B,O及其子视图的ContainerZ,并尝试从Z中设置B的位置动画,检查B是否在A前面.

  5. ios – 与容器视图通信的最佳实践是什么?

    我最近经常使用容器VC,我一直想知道主Vc和容器VC之间的最佳通信方式是什么.现在我正在使用通知,但我宁愿使用更好的东西.如何获取指向容器VC的指针,以便至少可以使用委托?

  6. ios – 编程嵌入UIViewController?

    我有一个带有一个容器视图的UIViewController的Storyboard设置,以便我可以在其中嵌入另一个UIViewController.在某种情况下,我需要更改嵌入式视图控制器.在我的故事板中,我的容器视图不能有两个区段.这导致我以编程方式进行.我的容器视图在我的故事板,没有连接的嵌入.现在从这一点开始,我如何以编程方式嵌入我所选择的UIViewController对象?

  7. ios – 使用Swift访问非默认的Cloudkit容器

    我有一个IOS8应用程序,它成功地将记录写入其默认的Cloudkit容器.现在我希望在OSX下的不同应用程序中读取和处理这些记录.我已经设置了具有iCloud访问权限的新应用程序,并选中了“指定自定义容器”选项.这已成功找到原始应用程序和我的容器没有错误要在Capabilities界面上修复.我的所有搜索都告诉我“同一个开发人员签署的两个应用程序可能共享同一个容器”但我找不到的任何教程文档都告诉我

  8. ios – 嵌入在容器视图中的UINavigationController,显示大小错误的表视图控制器

    我正在尝试找到解决这种情况的方法:我有一个UITabBarController它的一个segue连接到一个容器视图控制器(BannerViewController),我用来嵌入一个UINavigationController,导航控制器推送其他容器视图控制器(EventListContainerviewController),每个包含一个tableview控制器.这是我的故事板上的一个屏幕问题是最

  9. 在ios 6中,如何在View控制器中使用“容器视图”对象和嵌入在其中的表视图控制器之间使用传递数据?

    我有一个带标签和文本字段的视图控制器.我还添加了一个容器视图,它指向另一个具有一个部分和3行的表视图控制器,基本上是静态表视图.我无法找到任何文档/示例,告诉您如何在容器视图中嵌入容器视图和表视图容器的View控制器之间传递数据.我想要双方沟通?

  10. ios – 在容器视图中嵌入集合视图 – 顶部有额外的空白区域

    我有一个使用NavContoller作为它的初始VC的应用程序,然后它有一个根UIViewContoller,在上半部分包含一个UIView,在底部包含一个UIContainerView.在UIContanerView中,我嵌入了一个工作的UICollectionView,其中包含可以转换为详细视图的图像按钮.问题是,空白区域现在显示在UICollectionView的顶部.鉴于这个高约64像素,

随机推荐

  1. 从C到C#的zlib(如何将byte []转换为流并将流转换为byte [])

    我的任务是使用zlib解压缩数据包(已接收),然后使用算法从数据中生成图片好消息是我在C中有代码,但任务是在C#中完成C我正在尝试使用zlib.NET,但所有演示都有该代码进行解压缩(C#)我的问题:我不想在解压缩后保存文件,因为我必须使用C代码中显示的算法.如何将byte[]数组转换为类似于C#zlib代码中的流来解压缩数据然后如何将流转换回字节数组?

  2. 为什么C标准使用不确定的变量未定义?

    垃圾价值存储在哪里,为什么目的?解决方法由于效率原因,C选择不将变量初始化为某些自动值.为了初始化这些数据,必须添加指令.以下是一个例子:产生:虽然这段代码:产生:你可以看到,一个完整的额外的指令用来移动1到x.这对于嵌入式系统来说至关重要.

  3. 如何使用命名管道从c调用WCF方法?

    更新:通过协议here,我无法弄清楚未知的信封记录.我在网上找不到任何例子.原版的:我有以下WCF服务我输出添加5行,所以我知道服务器是否处理了请求与否.我有一个.NET客户端,我曾经测试这一切,一切正常工作预期.现在我想为这个做一个非托管的C客户端.我想出了如何得到管道的名称,并写信给它.我从here下载了协议我可以写信给管道,但我看不懂.每当我尝试读取它,我得到一个ERROR_broKEN_P

  4. “这”是否保证指向C中的对象的开始?

    我想使用fwrite将一个对象写入顺序文件.班级就像当我将一个对象写入文件时.我正在游荡,我可以使用fwrite(this,sizeof(int),2,fo)写入前两个整数.问题是:这是否保证指向对象数据的开始,即使对象的最开始可能存在虚拟表.所以上面的操作是安全的.解决方法这提供了对象的地址,这不一定是第一个成员的地址.唯一的例外是所谓的标准布局类型.从C11标准:(9.2/20)Apointe

  5. c – 编译单元之间共享的全局const对象

    当我声明并初始化一个const对象时.两个cpp文件包含此标头.和当我构建解决方案时,没有链接错误,你会得到什么如果g_Const是一个非const基本类型!PrintInUnit1()和PrintInUnit2()表明在两个编译单元中有两个独立的“g_Const”具有不同的地址,为什么?

  6. 什么是C名称查找在这里? (&amp;GCC对吗?)

    为什么在第三个变体找到func,但是在实例化的时候,原始变体中不合格查找找不到func?解决方法一般规则是,任何不在模板定义上下文中的内容只能通过ADL来获取.换句话说,正常的不合格查找仅在模板定义上下文中执行.因为在定义中间语句时没有声明func,并且func不在与ns::type相关联的命名空间中,所以代码形式不正确.

  7. c – 在输出参数中使用auto

    有没有办法在这种情况下使用auto关键字:当然,不可能知道什么类型的.因此,解决方案应该是以某种方式将它们合并为一个句子.这可用吗?解决方法看起来您希望默认初始化给定函数期望作为参数的类型的对象.您无法使用auto执行此操作,但您可以编写一个特征来提取函数所需的类型,然后使用它来声明您的变量:然后你就像这样使用它:当然,只要你重载函数,这一切都会失败.

  8. 在C中说“推动一切浮动”的确定性方式

    鉴于我更喜欢将程序中的数字保留为int或任何内容,那么使用这些数字的浮点数等效的任意算术最方便的方法是什么?说,我有我想写通过将转换放在解析的运算符树叶中,无需将表达式转化为混乱是否可以使用C风格的宏?应该用新的类和重载操作符完成吗?解决方法这是一个非常复杂的表达.更好地给它一个名字:现在当您使用整数参数调用它时,由于参数的类型为double,因此使用常规的算术转换将参数转换为double用C11lambda……

  9. objective-c – 如何获取未知大小的NSArray的第一个X元素?

    在objectiveC中,我有一个NSArray,我们称之为NSArray*largeArray,我想要获得一个新的NSArray*smallArray,只有第一个x对象…

  10. c – Setprecision是混乱

    我只是想问一下setprecision,因为我有点困惑.这里是代码:其中x=以下:方程的左边是x的值.1.105=1.10应为1.111.115=1.11应为1.121.125=1.12应为1.131.135=1.14是正确的1.145=1.15也正确但如果x是:2.115=2.12是正确的2.125=2.12应为2.13所以为什么在一定的价值是正确的,但有时是错误的?请启发我谢谢解决方法没有理由期望使用浮点系统可以正确地表示您的帖子中的任何常量.因此,一旦将它们存储在一个双变量中,那么你所拥有的确切的一

返回
顶部