问题标签 [copy-elision]
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++ - 复制省略可见副作用
考虑这段代码:
当我编译时
g++ -std=c++11 -fno-elide-constructors test.cpp
输出是
ctor ctor 副本 0
这是我所期望的,因为 in Foo b = 10
,10
是从 隐式构造的int
,然后b
是从 构造的副本Foo
。此外,我的复制构造函数不做任何事情,所以成员_a
仍然存在0
(因为它是类内初始化的)。
但是,当我使用复制省略时
g++ -std=c++11 test.cpp
输出是
演员 演员 10
至少可以说这是令人惊讶的。我知道这里省略了复制构造函数,但这是一个严重的副作用(成员一次初始化为 0 和一次初始化为 10 的事实),因为它会影响代码路径的其余部分。
这种行为正常吗?
c++ - 自动和复制省略
当使用 auto 并提交到特定类型时,复制省略的确切规则是什么?(请参阅:GotW - 几乎总是自动)。
据我了解,移动/复制构造函数必须是可访问的,即使它不常用。但是,在下面的示例中, unique_ptr和fstream之间有什么区别?(与noexcept 有关?)
c++ - 返回不能按值复制的对象
我有一个对象,它的复制操作太慢了,所以我决定这样delete
做并强制用户只移动。无论如何,这个对象伤口的副本没有多大意义。但后来我有这个功能:
即使这里发生了复制省略并且没有调用复制构造函数,这也无法编译,因为需要复制构造函数存在并且可以访问。这是我的第二次尝试:
这编译。耶!
但是在尝试使用它时又出现了一个新问题:
这又需要一个复制构造函数。即使明确使用move,我也无法让它工作:
我来的唯一解决方案是:
但x
必须是非常量的,因为它稍后会被改变。
如何处理?
c++ - 复制省略误区
编译后
g++ Copy.cpp -std=c++11 -fno-elide-constructors
输出是:
定义常数
复制构造
复制构造
我的问题是:为什么 2 Copy Consr ?我认为只需要 1 份副本。
我可能猜测 func1() 抛出了一个临时对象,并且这个临时对象需要被复制到另一个内存区域,并且必须再次从该区域复制 func2() 参数,但它对我来说是模糊的。
你能详细解释一下吗?
c++ - 为什么复制省略如此有限?
我关心的两种复制省略形式非常有限。它只允许在 return 语句中和使用临时变量初始化变量时。所以这些不涉及复制省略:
这是什么原因?这是技术限制..还是..?
c++ - 模板类调用过多的析构函数 (N)RVO 优化
我正在尝试编写自己的智能指针 (C++11) 和堆栈有一个问题,可以通过下一个示例来解释:
输出:
如您所见,这里有很多析构函数。在我看来,复制省略和模板构造函数之间的交互存在一些问题,但我不知道这种错误可能是什么原因。我试图通过添加explicit
复制构造函数和强制编译器使用我的模板构造函数来解决问题:
得到下一个输出:
这里一切看起来都不错,但它看起来不像一个干净的解决方案。有更好的选择吗?
c++ - 指向堆栈分配对象和移动构造的指针
注意:这是对我不久前发布的问题的完整重新措辞。如果您发现它们重复,请关闭另一个。
我的问题很笼统,但似乎可以根据一个具体的简单示例更容易地解释它。所以想象一下我想模拟办公室的用电量。让我们假设只有光和加热。
重点是:
1.Time
不能移动为数据成员Light
,或者Heating
因为它的更改不是来自这些类中的任何一个。
2.Time
不必作为参数显式传递给Light
. 实际上,Light
在程序的任何部分都可能存在不希望Time
作为参数提供的引用。
现在,Simulation
只要不是复制/移动构造,就可以完美找到。因为如果是,Light
也将构造复制/移动,并且默认情况下,指向时间的指针将指向复制/移动Time
的旧Simulation
实例中的。然而,Simulation
实际上是SimulationBuilder::build()
在返回语句和对象创建之间构建的复制/移动main()
现在有很多方法可以解决这个问题:
1:依靠复制省略。在这种情况下(在我的真实代码中),标准似乎允许复制省略。但不是必需的,事实上,它并没有被 clang -O3 忽略。更准确地说,clang 省略Simulation
了复制,但确实将移动 ctor 称为Light
. 另请注意,依赖于实现相关的时间并不可靠。
2:在中定义一个move-ctor Simulation
:
这确实有效,但这里的大问题是它削弱了封装:现在Simulation
必须知道Light
在移动过程中需要更多信息。在这个简化的例子中,这并不算太糟糕,但是想象timePtr
不是直接在Light
而是在它的一个子子子成员中。那我得写
这完全打破了封装和得墨忒耳定律。即使在委派职能时,我也觉得这很可怕。
3:使用某种观察者模式,在复制/移动构造时Time
被观察Light
并发送消息,以便Light
在接收消息时更改其指针。我必须承认我懒得写一个完整的例子,但我认为它会很重,我不确定增加的复杂性是否值得。
4:在中使用拥有指针Simulation
:
现在当Simulation
被移动时,Time
内存不是,所以指针 inLight
不会失效。实际上这是几乎所有其他面向对象语言所做的,因为所有对象都是在堆上创建的。目前,我赞成这个解决方案,但仍然认为它并不完美:堆分配可能会很慢,但更重要的是它看起来并不习惯。我听说 B. Stroustrup 说你不应该在不需要时使用指针,而需要意味着或多或少是多态的。
Simulation
5:就地构造,不被返回SimulationBuilder
(然后复制/移动ctor/assignmentSimulation
可以全部删除)。例如
现在我的问题如下:
1:你会使用什么解决方案?你想到另一个吗?
2:你觉得原来的设计有问题吗?你会怎么做才能修复它?
3:你遇到过这种模式吗?我发现它在我的代码中很常见。一般来说,这不是问题,因为Time
它确实是多态的,因此是堆分配的。
4:回到问题的根源,即“不需要移动,我只想在原地创建一个不可移动的对象,但编译器不允许我这样做”为什么没有C++ 中的简单解决方案,是否有另一种语言的解决方案?
c++ - 按值传递临时值时如何避免移动省略?
在以下代码中:
Widget 对象将始终就地构造(在 foo 函数内部),因此不会发生移动构造(至少对于我尝试过的所有编译器)。以实际发生移动构造的方式(没有显式移动,即使用std :: move)将临时值传递给函数的简单示例是什么?
c++ - 如何使用 C++11 移动语义从函数返回 std::vector?
我知道 C++11 有来自这个链接的移动语义: 现代 C++ 风格的元素
但它没有介绍如何使用移动语义返回向量。这该怎么做?
c++ - C中的返回值优化和复制省略
有些人不知道在 C 中可以按值传递和返回结构。我的问题是编译器在返回 C 中的结构时会制作不必要的副本。C 编译器(如 GCC)是否使用返回值优化(RVO)优化,或者这只是 C++ 的概念?我所读到的关于 RVO 和复制省略的所有内容都是关于 C++ 的。
让我们考虑一个例子。我目前正在 C 中实现双双数据类型(或者更确切地说是 float-float,因为我发现它很容易进行单元测试)。考虑以下代码。
编译器会制作doublefloat
我返回的值的临时副本还是可以省略临时副本?
C 中的命名返回值优化 (NRVO) 怎么样?我有另一个功能
在这种情况下,我将返回一个命名结构。这种情况下的临时副本可以省略吗?
应该说这是 C 的一个普遍问题,我在这里使用的代码示例只是示例(当我优化它时,无论如何我都会使用带有内在函数的 SIMD)。我知道我可以查看程序集输出以了解编译器的作用,但我认为这是一个有趣的问题。