move-semantics 相关问题

移动语义是一种编程语言功能,当源对象是临时对象或其他过期对象时,允许复制操作被更有效的“移动”替换。

看起来 std::move_iterator 只适用于字符串数据类型

如果容器具有字符串类型的数据,则可以使用 std::move_iterator 将数据从源容器移动到目标容器。 std::move_iterator 不与其他数据一起操作

回答 1 投票 0

如何将 rust 结构“转换”为另一个相同类型(相同的字段/布局)而不复制所有成员

我在一个模块中有一个私有类型,它与另一种类型具有相同的字段。我无法相互导入(以某种方式共享类型),因为这会导致循环依赖,而且会非常

回答 1 投票 0

在模式匹配期间防止移动语义

我这里有一个愚蠢的例子,只是为了演示我在使用另一个库和模式匹配时遇到的问题。 结构人{ 名称: 字符串, 年龄:i32, 选择:选择 } #[推导(

回答 2 投票 0

我应该始终继续使用 `sink` 构造函数或 setter 参数吗?

结构 TestConstRef { std::字符串str; 测试(const std::string& mStr) : str{mStr} { } }; 结构测试移动{ std::字符串str; 测试(std::string mStr) : str{std::move(mStr)} { } }; ...

回答 2 投票 0

C++11 移动语义行为特定问题[重复]

我已阅读以下文章,它对移动语义有了很好的了解: 有人可以向我解释一下移动语义吗? 但我仍然无法理解以下关于我的事情...

回答 2 投票 0

标准算法的 lambda 应该接受什么样的参数?

所以我昨天在 youtube 上观看 C++ 视频,遇到一个关于 C++-11 右值引用和移动语义的视频。我想我从广义上理解了这个概念,但是今天当我...

回答 1 投票 0

为什么添加默认的移动赋值运算符会破坏标准交换函数的编译?

在下面的代码中,如果移动赋值未注释,则交换函数将停止程序的编译。我在所有 3 个主要编译器(GCC、Clang、MSVC)上观察到了这种行为。 #包括 在以下代码中,如果未注释移动分配,则交换函数将停止程序的编译。我在所有 3 个主要编译器(GCC、Clang、MSVC)上都观察到了这种行为。 #include <utility> #include <memory> struct test { test() = default; test(test&& other) noexcept = default; //test& operator=(test&& other) noexcept = default; test(const test& other) : ptr(std::make_unique<int>(*other.ptr)) {} test& operator=(test other) noexcept { std::swap(*this, other); return *this; } std::unique_ptr<int> ptr; }; Godbolt 测试:https://godbolt.org/z/v1hGzzEaz 研究标准库实现,他们使用 SFINAE 或概念来启用/禁用 std::swap 重载,并且当特殊函数未注释时,由于某种原因,某些特征会失败(libstdc++ 上的 is_move_constructible 和/或 is_move_assignable)。 我的问题是:为什么添加默认的特殊成员函数会阻止标准库将类型视为可移动? std::move的主要实现在内部使用移动分配,类似于。 template <typename T> void swap(T& a, T& b) { T c = std::move(a); a = std::move(b); b = std::move(c); } 这意味着移动分配需要对您的类型有效,但事实并非如此。 如果你调用移动赋值运算符,你会得到一个错误: <source>:18:15: error: use of overloaded operator '=' is ambiguous [...] [...] | <source>:9:11: note: candidate function 9 | test& operator=(test&& other) noexcept = default; | ^ <source>:15:11: note: candidate function 15 | test& operator=(test other); | ^ 这两个运算符都可以使用 xvalue 进行调用,并且两者都不是更好的匹配。 std::swap 受到限制,因此只有 MoveAssignable 类型可以交换,而你的类型则不能。 即使你可以打电话std::swap,你也不能同时打电话 依赖 std::swap 的默认实现,它使用 operator= 用 operator= 定义 std::swap 这将是无限递归,因为 = 和 std::swap 的定义是循环的。 解决方案 您可以为您的类型定义自定义 swap,这样您就不再依赖 std::swap。 只保留 operator=(test),看起来像: test& operator=(test other) noexcept { swap(*this, other); // custom function, not std::swap return *this; } 您还可以手动定义单独的 operator=(const test&) 和 operator=(test&&) ,以便 std::swap 将使用移动赋值运算符,并且重载决策中不会有歧义。

回答 1 投票 0

std::move 和 std::shared_ptr 参数按值传递

考虑以下代码: #包括 #包括 班级测试 { 民众: 测试(int t):t(t){} 整数t; }; 无效测试(std::shared_ptr t) { 标准...

回答 1 投票 0

为什么C++中的移动语义在函数签名中有右值引用

考虑下面的移动赋值运算符: 类我的类{ 私人的: ssize_t buf_size; 无效* buf_ptr; 民众: MyClass &operator=(MyClass &&rhs) { 如果(这个!= &rhs){

回答 1 投票 0

编译器可以删除特定数据成员的副本吗?

获取此代码: struct Bar { //有非默认的复制构造函数 酒吧()=默认; 酒吧(常量酒吧&){} }; struct LargeObject { //有默认的复制构造函数 std::数组 获取此代码: struct Bar { //has non-default copy-constructor Bar() = default; Bar(const Bar&) {} }; struct LargeObject { //has default copy-constructor std::array<char, 1000> m_chars; }; struct Foo { Bar m_bar; LargeObject m_obj; }; Foo func() { Foo f; return f; } 当用户指定复制构造函数时,编译器无法删除副本。当类的成员具有非默认复制构造函数时该怎么办?在此代码中,当从 f 返回 func 时,编译器是否可以删除 m_obj 的副本,还是必须复制所有内容? 你的问题是基于一个错误的前提。编译器完全有权删除这样的副本,无论类本身或其成员之一是否具有非默认复制(或移动)构造函数。自 C++11 以来引入的复制省略规则的好处是允许这种优化,即使它违反了 as-if 规则。 如果做不到这一点,复制省略就没有那么有用了;即使只有一个智能指针(具有自定义复制和移动构造函数)的类也没有资格使用 RVO,除非编译器可以肯定地证明没有违反 as-if 规则。 在您的特定场景中,编译器可以在启用优化的情况下(这不是强制性的,因为您依赖于非强制性 NRVO,而不是简单 RVO 的 C++17 保证复制省略)通过以下方式实现 func直接将 Foo 对象构建到调用者提供的存储中,而不使用必须移动/复制回调用者的单独 Foo f。

回答 1 投票 0

运算符重载:修改临时对象或创建新对象

我在我们的项目中看到了以下代码,并问自己有什么技术和心理影响: A类{ 民众: A(常量 A&); A(A &&); 〜A(); 操作...

回答 2 投票 0

我自己的智能指针实现正在创建移动操作问题

在下面的代码中,输出结果为空白,而不是构造函数和析构函数的打印输出。没有移动操作,代码运行良好。我不知何故搞乱了移动操作,

回答 1 投票 0

使用用户定义的构造函数移动类型的构造,该构造函数接受使用不完整类型实例化的模板类型参数

试图理解为什么这段代码不能用 gcc 和 clang 编译,但可以用 msvc 编译。 编译器资源管理器 #包括 类不完整; 模板 结构

回答 1 投票 0

当使用C++的移动语义时,内存中会发生什么?

我试图理解C++的移动语义、移动构造函数、移动赋值运算符、std::move()。 让我们考虑以下示例: #包括 无效 swapWithMove(int& ...

回答 1 投票 0

为什么std::move中使用std::remove_reference?

我尝试实现 std::move,它使用 std::remove_reference,但似乎没有它也能工作。请给我一个例子,如果没有 std::remove_reference,我的实现将会失败。

回答 2 投票 0

匹配多个盒装值

我有以下代码,可以正常编译 #[导出(调试、PartialEq、克隆)] pub 枚举表达式 { 常量(i32), 负(方框), 添加(框,框 我有以下代码,可以正常编译 #[derive(Debug, PartialEq, Clone)] pub enum Expression { Const(i32), Neg(Box<Expression>), Add(Box<Expression>, Box<Expression>), } fn simplify(expr: &Expression) -> Expression { match expr { Expression::Neg(x) => match **x { Expression::Const(n) => Expression::Const(-n), _ => expr.clone() }, // GIVES ERROR // Expression::Add(x, y) => match (**x, **y) { // (Expression::Const(n), Expression::Const(m)) => Expression::Const(n + m), // _ => expr.clone() // }, Expression::Add(x, y) => match **x { Expression::Const(n) => match **y { Expression::Const(m) => Expression::Const(n + m), _ => expr.clone() } _ => expr.clone() } _ => expr.clone() } } 但是,如果我用注释掉的版本替换 Expression::Add 臂,则会出现以下编译器错误 error[E0507]: cannot move out of `**x` which is behind a shared reference --> src/lib.rs:21:41 | 21 | Expression::Add(x, y) => match (**x, **y) { | ^^^ move occurs because `**x` has type `Expression`, which does not implement the `Copy` trait error[E0507]: cannot move out of `**y` which is behind a shared reference --> src/lib.rs:21:46 | 21 | Expression::Add(x, y) => match (**x, **y) { | ^^^ move occurs because `**y` has type `Expression`, which does not implement the `Copy` trait For more information about this error, try `rustc --explain E0507`. 是否有理由我们可以与单独的 **x 匹配,但不能在像 (**x, **y) 这样的元组中匹配?前者实际上是被转换还是隐藏了一些语法糖?有没有比两个嵌套匹配更简单的方法来编写这个 Add 臂? 编辑:我还看到有一个 ref 关键字,它应该解决类似的问题,但是将我的元组匹配表达式更改为 (ref **x, ref **y) 会产生语法错误(error: expected expression, found keyword ref)。 TL;DR: 与 (&**x, &**y) 比赛。 这里发生的事情很有趣。 TL;DR 是:当您 match v {} 时,您不会阅读 v。您为 v 创建了一个 地方。 A place 是我们可以阅读的东西。或者写信给。或者什么也不做。重要的是,仅仅创造场所并不涉及这样的操作。您可以稍后读/写它,但是当您创建它时,它只是一个地方。 在您的 match 中,x 和 y 的类型为 &Box<Expression>。当我们match **x时,我们不读x。因此,我们也不会移动**x。我们所做的是为**x创造一个地方。然后我们将这个地方与 Expression::Const(n) 进行匹配。现在我们读取 x 并从中提取 n。但是 n 是 i32 - Copy - 所以这很好。 相反,当您使用元组 (**x, **y) 时,由于您不直接与 **x 和 **y 匹配,因此您确实会读取它们。因为你读了它们,而它们不是 Copy (Expression),所以你就离开了它们。现在这是一个错误,因为您无法移出共享引用。您之后匹配它们,但它们已经移动了。 你可以试试match(x.as_ref(),y.as_ref())

回答 2 投票 0

在构造函数中将对象移动到成员

我有几个类,其中的对象是另一个类的成员。 ARX类; PID类; 类模拟 { 阿克斯阿克斯; PID; }; 我想在“外部”构建所有成员,......

回答 0 投票 0

将 std::move shared_ptr 与条件运算符一起使用时的奇怪行为

我在 shared_ptr 上使用 std::move 编写一些 C++ 代码,得到了非常奇怪的输出。我已经简化了我的代码如下 int func(std::shared_ptr&& a) { 返回 0; } 国际马...

回答 0 投票 0

高阶函数参数中的`&&`可以作为转发引用吗?

转发(或通用引用)的规范示例如下: 模板 void f(T&& 参数); IE。 “如果声明变量或参数具有类型......

回答 1 投票 0

是否保证容器会在 std::move 期间销毁现有对象?

考虑以下示例: #包括 #包括 A类{ 民众: A(const A&) = 默认值; A(A&&) = 默认; A& 运算符=(const A&) =

回答 1 投票 0

© www.soinside.com 2019 - 2024. All rights reserved.