标签: move-semantics

移动返回时调用的构造函数而不是复制

今天我发现这段代码并没有像我期望的那样工作。根据我的知识,对于 L 值,应该调用复制构造函数,而对于 R 值,应该选择移动构造函数。否则它的目的是什么,std::move实际上什么也不做,只是转换为 R 值。我原以为return obj会调用复制构造函数,但它调用了 move。我知道复制在这里毫无用处,但这就是规则。如果我的复制构造函数有副作用,这就是我的情况,该怎么办(我知道它不应该,但从技术上讲它可以 - 例如这里:std::cout 调用)。标准中有什么允许这种行为的吗?另外我怎样才能强制复制?

#include <iostream>

class X
{
public:
    X() = default;

    X(const X& r): i(r.i)
    {
        std::cout << "copy ctor" << std::endl;
    }

    X(const X&& r): i(r.i)
    {
        std::cout << "move ctor" << std::endl;
    }
    int i = 0;
};

X foo()
{
    X obj;
    obj.i = 10;
    return obj;
}

int main()
{
    X x = foo();
}
Run Code Online (Sandbox Code Playgroud)

移动演员

移动演员

move-semantics c++11

1
推荐指数
1
解决办法
1305
查看次数

如何为模板类的 const ref 成员定义移动赋值运算符

我有以下模板类,其中成员是const ref类型。对象的复制被禁用,并且只需要移动对象和移动赋值运算符。

Q1:如何const ref type正确实现移动赋值运算符(我所做的是否正确)?

Q2:为什么会这样

MyClass<int> obj2(std::move(obj));   // will work with move ctor
MyClass<int> obj3 = std::move(obj2); // also move ctor called: Why?
Run Code Online (Sandbox Code Playgroud)

发生了?

Q3:在main()移动实例中是否可以调用using print()。是UB吗?

我正在使用Visual Studio 2015 (v140)。这是我的代码:

#include <utility>
#include <iostream>

template<typename Type>
class MyClass
{
    const Type& m_ref;  // const ref type
public:
    explicit MyClass(const Type& arg): m_ref(std::move(arg)){}

    // coping is not allowed
    MyClass(const MyClass&) = delete;
    MyClass& operator=(const MyClass&) = delete;

    // …
Run Code Online (Sandbox Code Playgroud)

c++ language-lawyer const-reference move-semantics c++11

1
推荐指数
1
解决办法
1406
查看次数

如何强制 std::vector 使用移动构造函数而不是复制构造函数?

我想在我的应用程序中使用移动语义,而不是复制数据。\n以下是代码:

\n\n
using namespace std;\n\nstruct TestData\n{\n    TestData(const TestData&) = delete;\n    TestData& operator=(const TestData&) = delete;\n    TestData(TestData &&other) = default;\n    TestData& operator=(TestData &&other) = default;\n\n    TestData() { std::cout << "TestData()" << std::endl; }\n    ~TestData() noexcept {\n        if(ptr != null) delete []ptr;\n        std::cout << "~TestData(), ptr = " << (ptr == nullptr ? "nullptr" : "not null") << std::endl; \n    }\n    int x;\n    char *ptr = nullptr;\n};\n\nvoid add(std::vector<TestData> &vector)\n{\n    TestData d;\n    d.x = 1;\n    d.ptr = new char[12];\n    memcpy(d.ptr, "Test string", 11);\n …
Run Code Online (Sandbox Code Playgroud)

c++ gcc move-semantics c++11

1
推荐指数
1
解决办法
2518
查看次数

移动构造函数与复制省略

有人可以向我解释一件事吗?从一方面来看,它的move constructor设计目的是通过消除不必要的复制对象来优化内存和处理器的使用,但从另一面来看,几乎所有地方move constructor都会使用编译器使用复制省略move ctor,禁用?的使用。这不是不合理吗?

c++ constructor move-semantics copy-elision

1
推荐指数
1
解决办法
718
查看次数

函数重载。函数内部的操作是一样的。我必须重写所有内容吗?

我有一堆带有 inputxy. 我允许输入类型通过引用传递(如果它已经存在)和通过临时输入(使用&&)(如果不存在并且需要创建一个临时对象)。

基本上,我定义和重载函数如下

double foo(const std:::vector<int> & x, const std:::vector<int> &  y){
// Do something
}
double foo(const std:::vector<int> & x,std:::vector<int>&& y){
// Do something
}
double foo(std:::vector<int>&& x,const std:::vector<int> &  y){
// Do something
}
double foo(std:::vector<int>&& x,std:::vector<int>&& y){
// Do something
}
Run Code Online (Sandbox Code Playgroud)

//Do something 完全相同,但唯一的区别是输入类型。有没有一种方法可以在没有太多冗余的情况下简化代码?我不想有foo(std:::vector<int> x,std:::vector<int> y)内存问题。

编辑:有时我还必须稍微修改输入。可能有三种类型的不同子集std::vector<int> &,std::vector<int> &&,const std::vector<int> &xy

正如@AVH(谢谢!)指出的那样,如果它只是 from std::vector<int> &&,const std::vector<int> &const std::vector<int> &应该足以完成这项工作。

结合@Ken Wayne …

c++ move-semantics c++11

1
推荐指数
1
解决办法
61
查看次数

我可以在返回多个值时避免复制,同时保留我的返回类型吗?

如果我们写如下函数:

auto foo() {
    Foo foo { /* ... */ };
    do_stuff(foo);
    return foo;
}
Run Code Online (Sandbox Code Playgroud)

然后NRVO应该启动,这样foo就不会在返回时被复制。

现在假设我想返回两个不同的值:

auto foo() {
    Foo foo { /* ... */ };
    Bar bar { /* ... */ };
    do_stuff(foo, bar);
    return std::make_tuple(foo, bar);
}
Run Code Online (Sandbox Code Playgroud)

这种幼稚的实现可能会触发构建每个FooBar( GodBolt)的两个副本。

我应该如何最好地修改我的代码以避免这种复制,而不会弄乱我的返回类型?

c++ move-semantics copy-elision nrvo stdmove

1
推荐指数
1
解决办法
50
查看次数

为什么对于 std::vector::resize() 的一个重载忽略了移动操作的抛出?

在 C++ 标准vector.capacity部分,它为 定义了两个重载resize()。(另见https://en.cppreference.com/w/cpp/container/vector/resize

此重载要求类型 T 是MoveInsertableand DefaultInsertable

constexpr void resize(size_type sz);
Run Code Online (Sandbox Code Playgroud)

另一个重载要求类型 T 是CopyInsertable

constexpr void resize(size_type sz, const T& c);
Run Code Online (Sandbox Code Playgroud)

标准中提到的部分的第 16 条规定了第一次重载:

如果非 Cpp17CopyInsertable T的移动构造函数引发异常,则不会产生任何影响。

但是对于第二次重载,它指出:

如果抛出异常,则没有任何影响。

第二个重载中没有提到移动构造函数的抛出。为什么?

c++ stdvector move-semantics

1
推荐指数
1
解决办法
70
查看次数

“由于在生成器中使用而发生移动”错误在 Rust 中意味着什么?

我有关于发电机的这个问题:

use tokio::runtime::Runtime;
use tokio::task::JoinHandle;
use std::sync::Arc;

pub fn run(f: Box<dyn Fn() -> Result<(), ()> + Send>) {
    f();
}

fn main() {
    let x = Arc::new(0);
    run(Box::new(move ||{
        let rt = Runtime::new().unwrap();
        let _t = rt.block_on(async move {
            let y = x;
        });
        Ok(())
    }));
}
Run Code Online (Sandbox Code Playgroud)

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=de28ecf9e5baf6a017cd6a5230d74d7b

错误:

error[E0507]: cannot move out of `x`, a captured variable in an `Fn` closure
  --> src/main.rs:13:41
   |
10 |       let x = Arc::new(0);
   |           - captured outer variable
...
13 |           let …
Run Code Online (Sandbox Code Playgroud)

smart-pointers move-semantics rust

1
推荐指数
1
解决办法
213
查看次数

移出泛型类型的共享引用

我正在尝试创建一个函数,该函数使用迭代器&[Vec<u64>]i64每行中最大的一个返回元组“坐标”向量。我有它在具体类型上工作,但我希望它是通用的,T并且限制为可迭代类型。到目前为止我的代码:

fn find_largest_per_row<T>(input: &[T]) -> Vec<(usize, usize)> 
where
    T: IntoIterator<Item = u64>,
{
    input
        .iter()
        .enumerate()
        .map(|(r, v)| {
            v.into_iter()
                .enumerate()
                .max_by_key(|&(_, v)| v)
                .map(|(c, _)| (r, c))
                .unwrap()
        })
        .collect::<Vec<_>>()
}
Run Code Online (Sandbox Code Playgroud)

我越来越:

fn find_largest_per_row<T>(input: &[T]) -> Vec<(usize, usize)> 
where
    T: IntoIterator<Item = u64>,
{
    input
        .iter()
        .enumerate()
        .map(|(r, v)| {
            v.into_iter()
                .enumerate()
                .max_by_key(|&(_, v)| v)
                .map(|(c, _)| (r, c))
                .unwrap()
        })
        .collect::<Vec<_>>()
}
Run Code Online (Sandbox Code Playgroud)

我该如何解决?我意识到T是一个参考,所以我尝试了.cloned(),但这没有用。

另外,对于IntoIterator<Item=u64>,我需要指定u64还是可以提供更通用的东西?

generics traits move-semantics rust

1
推荐指数
1
解决办法
48
查看次数

类似乎可以使用用户定义的析构函数移动

我想弄清楚为什么这段代码不能编译?我已经创建了用户定义的析构函数,因此不应创建移动构造函数和移动赋值运算符。那么为什么复杂化失败,说我的班级不符合要求?

#include <iostream>
#include <concepts>
#include <type_traits>

template<class T>  requires (!std::movable<T>)
struct Singleton
{

};

struct Widget 
{
  ~Widget() = default;
};

int main()
{
  auto x = Singleton<Widget>{};
}
Run Code Online (Sandbox Code Playgroud)

编辑。这个版本也是如此。

#include <iostream>
#include <concepts>
#include <type_traits>

extern void fun();

template<class T>  requires (!std::movable<T>)
struct Singleton
{

};

struct Widget 
{
  ~Widget() 
  {
    fun();
  } 
};

int main()
{
  auto x = Singleton<Widget>{};
}
Run Code Online (Sandbox Code Playgroud)

错误信息

:23:28: 注意: 不满足约束: 替换“模板需要 !(movable) > struct Singleton [with T = Widget]”: :23:28: 从这里需要 :8:8: …

c++ move-semantics

1
推荐指数
1
解决办法
61
查看次数