- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
move 操作应该是 noexcept
;首先是直观和合理的语义。第二个参数是运行时性能。来自核心指南,C.66 , "使 move 操作 noexcept":
A throwing move violates most people’s reasonably assumptions. A non-throwing move will be used more efficiently by standard-library and language facilities.
std::vector::push_back
的情况或者 friend 需要增加缓冲区。标准在这里需要强大的异常保证,如果这是
noexcept
,这只能将元素 move 构造到新缓冲区中。 - 否则,必须复制。我明白了,差异在基准测试中是可见的。
noexcept
对性能的积极影响。 move 语义。浏览标准库(
libcxx
+
grep
),我们看到
std::move_if_noexcept
存在,但它几乎不在库本身中使用。同样,
std::is_noexcept_swappable
仅用于充实条件
noexcept
预选赛。这与现有声明不符,例如 Andrist 和 Sehr 来自“C++ High Performance”的声明(第 2 版,第 153 页):
All algorithms use
std::swap()
andstd::move()
when moving elements around, but only if the move constructor and move assignment are marked noexcept. Therefore, it is important to have these implemented for heavy objects when using algorithms. If they are not available and exception free, the elements will be copied instead.
std::vector::push_back
的代码路径? ,当喂食 std::is_nothrow_move_constructible
时运行得更快类型? noexcept
时,编译器何时能够可靠地生成运行时效率更高的代码,是否有明显的例子?指南? 最佳答案
背景:我指的是std::vector
使用 noexcept 作为“vector
悲观化”。我声称vector
悲观是任何人关心放置 noexcept
的唯一原因关键字进入语言。此外,vector
悲观化仅适用于元素类型的 move 构造函数。我声称将您的 move 分配或交换操作标记为 noexcept
没有“游戏内效果”;撇开它是否在哲学上令人满意或在风格上正确不谈,您不应该期望它对您的代码性能产生任何影响。
让我们检查一个真正的库实现,看看我离错误有多近。 ;)
move_if_noexcept
仅限内部__construct_{forward,backward}_with_exception_guarantees
,仅在 vector 重新分配中使用。variant
的赋值运算符.内__assign_alt
,代码标签在 is_nothrow_constructible_v<_Tp, _Arg> || !is_nothrow_move_constructible_v<_Tp>
上调度.当您这样做时myvariant = arg;
,默认的“安全”方法是构造一个临时的 _Tp
来自给定的 arg
,然后销毁当前放置的替代方案,然后 move 构造该临时 _Tp
进入新的替代方案(希望不会抛出)。但是,如果我们知道 _Tp
不能直接从 arg
构造,我们就这样做;或者,如果 _Tp
的 move 构造函数正在抛出,因此“安全”方法实际上并不安全,那么它不会为我们购买任何东西,无论如何我们只会执行快速直接构造方法。optional
的赋值运算符不做任何这种逻辑。
variant
赋值,使用 noexcept move 构造函数实际上会损害(未优化)性能,除非您还将选定的转换构造函数标记为
noexcept
!
Godbolt.
string
附加/插入/分配。这是一个令人惊讶的。 string::append
拨打 __append_forward_unsafe
正在接受 SFINAE 检查 __libcpp_string_gets_noexcept_iterator
.当您这样做时s1.append(first, last)
,我们想做s1.resize(s1.size() + std::distance(first, last))
然后复制到这些新字节中。但是,这在三种情况下不起作用: (1) 如果 first, last
指向 s1
本身。 (2) 如果 first, last
正是input_iterator
s(例如从 istream_iterator
中读取),因此已知不可能迭代范围两次。 (3) 如果有可能对范围进行一次迭代可能会将其置于第二次迭代会抛出的错误状态。也就是说,如果第二个循环中的任何操作( ++
、 ==
、 *
)是非无异常(exception)的。所以在这三种情况中的任何一种情况下,我们都会采取“安全”的方法来构建一个临时 string s2(first, last)
然后 s1.append(s2)
. Godbolt. string::append
优化不正确。 (
EDIT: yes, it is. ) 见
"Attribute noexcept_verify
" (2018-06-12)。还有
observe in that godbolt对 libc++ 至关重要的操作是
rv == rv
,但它实际上在内部调用的那个
std::distance
是
lv != lv
.
string::assign
和
string::insert
.我们需要在修改字符串的同时迭代范围。所以我们需要要么保证迭代器操作是 noexcept,要么需要一种在抛出异常时“退出”我们的更改的方法。当然还有
assign
特别是,没有任何方法可以“取消”我们的更改。在这种情况下唯一的解决方案是将输入范围复制到临时
string
中。然后从中分配
string
(因为我们知道
string::iterator
的操作是 noexcept ,所以他们可以使用优化的路径)。
string::replace
不做这个优化;它总是将输入范围复制到临时
string
首先。
function
SBO。 libc++ 的 function
仅当存储可调用对象 is_nothrow_copy_constructible
时才使用其小缓冲区(当然小到可以装下)。在这种情况下,可调用对象被视为一种“仅复制类型”:即使您 move 构造或 move 分配 function
,存储的可调用对象将是复制构造的,而不是 move 构造的。 function
甚至根本不需要存储的可调用对象是可 move 构造的!any
SBO。 libc++ 的 any
仅当存储可调用对象 is_nothrow_move_constructible
时才使用其小缓冲区(当然小到可以装下)。不像 function
, any
将“move ”和“复制”视为不同的类型删除操作。packaged_task
SBO 不关心抛出 move 构造函数。它的 noexcept move 构造函数会很高兴地调用用户定义的可调用对象的 move 构造函数:
Godbolt.这导致调用
std::terminate
如果可调用的 move 构造函数确实抛出过。 (令人困惑的是,打印到屏幕上的错误消息使它看起来好像异常正在从
main
的顶部逃逸出来;但这实际上并不是内部发生的事情。它只是从
packaged_task(packaged_task&&) noexcept
的顶部逃逸出来并被暂停在那里
noexcept
。)
vector
悲观,您必须声明您的 move 构造函数 noexcept。我仍然认为这是一个好主意。variant
悲观化”,你还必须声明你所有的单参数转换构造函数 noexcept。然而,“variant
悲观化”只需要一个 move 构造;它不会一直降级为复制结构。因此,您可能可以安全地吃掉这笔费用。noexcept
可以在 libc++ 的 function
中启用小缓冲区优化.但是,这仅适用于 (A) 可调用和 (B) 非常小以及 (C) 没有默认复制构造函数的事物。我认为这描述了空集。别担心。noexcept
可以在 libc++ 的 string::append
中启用(可疑的)优化.但实际上没有人关心这个;而且,无论如何,优化的逻辑是有问题的。我非常在考虑提交一个补丁来删除那个逻辑,这将使这个要点过时。 (编辑:补丁 submitted ,还有 blogged 。)关于c++ - 标准库或编译器在哪里利用 noexcept move 语义( vector 增长除外)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66459162/
增长,则让
当我输入内容时,如何移动 p 段落下方的所有元素,即 contenteditable。 这是我的代码: body, html { margin: 0; padding: 0; backgr
我要解决的问题: 我有一个包含 div 的外部 div。 content 内部和外部 div 之间的边距应始终相同。 当内部 div 增长/收缩时,外部 div
这document Ulrich Drepper 称为“图书馆设计、实现和维护的良好实践”(第 5 页底部): [...] the type definition should always crea
有什么方法可以获取 QPainterPath 并将其展开,就像 Photoshop 中的“选择”>“增长...”(或“展开...”)命令一样? 我想获取从 QGraphicsItem::shape 返
假设,为了问题的目的,我们有一个内存池,最初分配了 n 个 block 。但是,当达到容量时,池想要增长并变成原来大小的两倍 (2n)。 现在可以使用 C 中的 realloc 完成此调整大小操作,但
假设,为了问题的目的,我们有一个内存池,最初分配了 n 个 block 。但是,当达到容量时,池想要增长并变成原来大小的两倍 (2n)。 现在可以使用 C 中的 realloc 完成此调整大小操作,但
我正在研究 boost 库的共享内存部分,为更大的项目做准备。我需要一个共享内存段,在初始化时我不一定知道它的大小,所以我的计划是增加这个段。 我的初始实现有一个存储在共享内存中的 boost::in
这个问题在这里已经有了答案: How to disable equal height columns in Flexbox? (4 个答案) What are the differences bet
我有一个包含子表的表。我不希望子表影响表格的宽度——在溢出的情况下,我希望两者独立滚动。此外,由于子表是基于切换显示的,所以我不希望主表行根据子表是否可见而跳转 Here's代码笔。 我想我可以用 t
我有一个带栏的页面设计,它可以有一个、两个或三个栏。这些列的大小应相同。 为此我使用了 flexbox,它很好,允许我添加/删除我的列并让浏览器处理列宽的大小调整。 现在,当列中的文本大于列的宽度时,
要求: 我需要根据数据增长一个任意大的数组。 我可以猜测大小(大约 100-200),但不能保证数组每次都能适合 一旦它增长到最终大小,我需要对其执行数值计算,因此我更愿意最终得到一个二维 numpy
我有一个 3x256 规则的规则集。每个规则映射到一个 3x3 的值网格,这些值本身就是规则。 规则示例: 0 -> [[0,0,0],[0,1,0],[0,0,0]] 1 -> [[1,1,1],
我有 3 个 div,如果我给前两个 div flex: 0.5,如果我给了 flex-wrap: wrap,最后一个 div 应该移动到下一行>。如果我错了,请指正。 以下是我的 html/css:
在文档和 Bootstrap v4 问题中 (here) ,我看不到任何支持 flex-grow 的计划,例如语法如下: I use all the space lef
要求: 我需要从数据中增加一个任意大的数组。 我可以猜测大小(大约 100-200),但不能保证每次都适合数组 一旦它增长到最终大小,我需要对其执行数值计算,因此我希望最终得到一个二维 numpy 数
我知道(并在互联网上阅读-包括此资源)。增加内存的逻辑是:如果len数组小于1024-golang将array乘以2,否则将len乘以1.25(并且我们在源代码中看到了这个问题https://gith
当输入长文本时,WPF TextBox 控件会增长。 这个问题已经在 Stackoverflow 中提出了 我也引用了一些答案,但我仍然没有找到有效的正确答案。 Here提到了同样的问题,但没有针对此
我在使用 Vaadin HorizonalLayout 时遇到问题 - 我希望左侧组件填充大部分水平空间,如 Fiddle 所示 但是,当我运行 Vaadin 应用程序时,这两个组件会平分屏幕。
关于这个fiddle , 当我点击 a href在这种情况下这是一个图像,我希望图像从 div 开始增长/过渡以通过过渡/缩放填充整个页面它被放置在其中。如果这不可能,我想用 div 的背景颜色填充页
关闭。这个问题需要更多focused .它目前不接受答案。 想改进这个问题吗? 更新问题,使其只关注一个问题 editing this post . 关闭 6 年前。 Improve this q
我是一名优秀的程序员,十分优秀!