问题标签 [copy-and-swap]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c++ - 什么是复制省略,它如何优化复制和交换的习惯用法?
我正在阅读Copy and Swap。
我尝试阅读有关 Copy Elision 的一些链接,但无法正确理解它的含义。有人可以解释一下这个优化是什么,特别是下面的文字是什么意思
这不仅仅是方便的问题,实际上也是一种优化。如果参数(s)绑定到左值(另一个非常量对象),则在创建参数时会自动制作对象的副本。但是,当 s 绑定到右值(临时对象,文字)时,副本通常会被省略,这样可以节省对复制构造函数和析构函数的调用。在参数被接受为 const 引用的赋值运算符的早期版本中,当引用绑定到右值时,不会发生复制省略。这会导致创建和销毁一个额外的对象。
c++ - 什么是复制和交换成语?
这个成语是什么,应该在什么时候使用?它解决了哪些问题?使用 C++11 时习语会发生变化吗?
尽管在很多地方都提到过,但我们没有任何单一的“它是什么”问题和答案,所以在这里。以下是之前提到的地方的部分列表:
c++ - 通过复制和交换与两个锁进行分配
借用Howard Hinnant 的示例并将其修改为使用复制和交换,这 op= 线程安全吗?
我相信这个线程安全(记住 op= 的参数是按值传递的),而我能找到的唯一问题是隐藏在地毯下的问题:复制 ctor。但是,这将是一个罕见的类,它允许复制分配但不允许复制构造,因此该问题同样存在于两种替代方案中。
鉴于自我分配是如此罕见(至少对于这个例子来说),如果它发生我不介意额外的副本,考虑这个 != &rhs 的潜在优化可以忽略不计或悲观化。与原始策略(下)相比,是否还有其他理由更喜欢或避免它?
顺便说一句,我认为这简洁地处理了复制ctor,至少对于这个类,即使它有点迟钝:
c++ - 公共朋友交换会员功能
在copy-and-swap-idiom的漂亮答案中,有一段代码我需要一些帮助:
他加了一条注释
还有其他主张我们应该为我们的类型专门化 std::swap,提供类内交换以及自由函数交换等。但这都是不必要的:任何正确使用交换都将通过不合格的调用,我们的函数会通过ADL找到。一个功能就可以了。
我friend
必须承认,我有点“不友好”。所以,我的主要问题是:
- 看起来像一个自由函数,但它在类体内?
- 为什么这不是
swap
静态的?它显然不使用任何成员变量。 - “任何正确使用交换都会通过 ADL 找到交换”?ADL 将搜索命名空间,对吗?但它是否也在类内部?还是从这里
friend
进来的?
附带问题:
- 使用 C++11,我应该用 s 标记我
swap
的 snoexcept
吗? - 使用 C++11 及其range-for,我应该在类
friend iter begin()
中friend iter end()
以相同的方式放置吗?我认为friend
这里不需要,对吧?
c++ - 安全分配和复制和交换习语
我正在学习 c++,我最近学习了(在堆栈溢出中)关于复制和交换习语的知识,我对此有一些疑问。因此,假设我有以下类使用复制和交换习语,例如:
我的问题是,假设我有另一个类,它有一个 Foo 对象作为数据但没有指针或其他可能需要自定义复制或分配的资源:
现在我有一系列问题:
上面为
Bar
类实现的方法和构造函数是否安全?使用了复制和交换来Foo
确保在分配或复制时不会造成任何伤害Bar
?在复制构造函数和交换中通过引用传递参数是强制性的吗?
是否可以说,当 的参数
operator=
按值传递时,为此参数调用复制构造函数以生成对象的临时副本,然后与该副本交换*this
?如果我通过引用传递,operator=
我会有一个大问题,对吧?是否存在这种习语无法在复制和分配时提供完全安全的情况
Foo
?
c++ - 为什么有些人使用交换进行移动任务?
例如,stdlibc++ 有以下内容:
为什么不直接将两个 __u 成员分配给 *this 呢?交换是否暗示 __u 被分配了 *this 成员,只是后来分配了 0 和 false ......在这种情况下,交换正在做不必要的工作。我错过了什么?(unique_lock::swap 只是对每个成员执行 std::swap )
c++ - 在可移动和不可复制的类上使用移动和交换习语是否有意义
如果我有一堂课,比如
如果我没有复制构造函数,按值实现 operator= 并交换是否有意义?它应该防止复制我的类对象,Foo
但允许移动。
这个类是不可复制的,所以我不应该能够复制构造或复制分配它。
编辑
我已经用这个测试了我的代码,它似乎有我想要的行为。
c++ - 重用复制和交换习语
我正在尝试将复制和交换习语放入可重用的混合中:
我打算通过 CRTP 将其混合:
但是,一个简单的测试表明它不起作用:
这只会打印两次“default”,既不打印“copy”也不打印“swap”。我在这里想念什么?
c++ - 使用带有复制和交换的模板类未解决的外部问题
使用模板类时出现链接器错误,我尝试按照此处的建议实现复制和交换习惯用法:
模板类,我们称之为“TemplateClass”,部分定义如下:
我已将实现放在一个单独的 TemplateClass.cpp 中,该模板包含在 .h 文件中。(编辑:如果一切都在 .h 文件中,我有同样的问题)
赋值运算符定义为:
交换方法定义为:
(别担心,我并没有真正将我的成员命名为“member1”等)
我有一个类似的类,它以相同的方式定义,但不是模板类。那里一切正常。但是,如果我有一个TestClass
有成员的类,TemplateClass< HandledClass > member
并且我在它的一种方法中进行调用,例如
我得到一个未解决的外部错误:
LNK2019:函数“public: class TemplateClass X & __thiscall TemplateClass X::operator=(class TemplateClass)”(...) 中未解析的外部符号“void __cdecl swap(class TemplateClass &, class TemplateClass &)”(...)在 TestClass.obj 中
或者换句话说:TestClass
调用TemplateClass<HandledClass>::operator=
中找不到的东西void swap( TemplateClass<HandledClass>, TemplateClass<HandledClass> )
。
所以我的问题是:为什么运营商找不到swap方法?
看起来它不是为模板参数编译的。是否有可能让编译器也编译友元 voids?
我可能会放弃这种friend void
方法并定义一个类内交换方法加上一个类外交换方法加上一个 std 命名空间中的一个,但我不知道它是否会这样工作,如果我想避免这种情况反正可能。
解决方案:
这完成了工作:
请注意我也必须删除 < T > 事件。
visual-c++ - 如何交换 MFC CString?
好的,所以我对复制和交换习语很感兴趣,我想我主要知道如何实现它。
但是,或者代码库使用MFC 的 CString 类作为字符串,这不会改变。
既然swap
必须(应该???)不是抛出,我不能做
因为这将创建一个可能抛出的临时 CString 对象。(加上它的低效。)
那我还剩下哪里?我应该添加一个try-catch吗?我真的应该允许这种(嗯,非常罕见的)内存不足的情况引发异常并使交换失败吗?
查看 CStrings 实现,似乎没有允许交换的成员或函数......