标签: move-semantics

将unique_ptrs从一个向量移动到另一个向量

我想将存储在未分类矢量中的unique_ptr移动到另一个矢量,该矢量将包含指针的排序矢量.

肯定移动unique_ptr不会自动擦除第一个向量中的元素?我怎样才能做到这一点?

我想做的例子:

std::vector<std::unique_ptr<T> > unsorted, sorted;
// fill the "unsorted" vector
while( unsorted.size() > 0 )
{
    const auto it = find_next_element_to_add_to_sorted(unsorted);
    sorted.push_back( std::move(*it) );
}
Run Code Online (Sandbox Code Playgroud)

我希望意图清楚.

更新:我的算法不允许就地排序.如果今天有人感觉很好(我没有问,请参阅上面的问题),请随意为这种情况实施并告诉我.我真的需要"按移动排序".我真的不明白为什么移动会昂贵得多.

c++ unique-ptr move-semantics c++11

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

返回的本地人自动xvalues

继我对此做出的评论之后:

将std :: vector传递给构造函数并移动语义 是否std::move在下面的代码中是必要的,以确保返回的值是xvalue?

std::vector<string> buildVector()
{
  std::vector<string> local;

  // .... build a vector

  return std::move(local);
}
Run Code Online (Sandbox Code Playgroud)

我的理解是这是必需的.我经常看到std::unique_ptr从函数返回时使用的这个,但是GManNickG发表了以下评论:

我的理解是,在一个return语句中,所有局部变量都是自动xvalues(到期值)并将被移动,但我不确定它是否仅适用于返回的对象本身.所以OP应该继续把它放在那里,直到我更加自信它不应该是.:)

任何人都可以澄清是否std::move有必要吗?

行为编译器是否依赖?

c++ move-semantics c++11

18
推荐指数
3
解决办法
1400
查看次数

在C++ 11中抛出时,异常是否使用移动语义?

http://www.drdobbs.com/cpp/practical-c-error-handling-in-hybrid-env/197003350?pgno=4

在本文中,Herb Sutter解释说,抛出异常需要异常的副本,因为它是作为临时创建的,因此使用a std::auto_ptr来绕过副本开销.根据C++ 11中提供的移动语义,这仍然是必要的吗?

c++ move-semantics c++11

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

移动std :: vector时是否需要保留容量?

请考虑以下代码:

std::vector vec;
vec.reserve(500);
size_t cap = vec.capacity();

std::vector newVec = std::move(vec);
assert(cap == newVec.capacity());
Run Code Online (Sandbox Code Playgroud)

在几乎任何你遇到的实现中,这都可行.我不关心实现什么.我想知道标准需要什么.移动的vector容量是否与原始容量相同?或者断言触发器?

c++ stdvector language-lawyer move-semantics c++11

18
推荐指数
2
解决办法
581
查看次数

什么时候返回语句需要显式移动?

对另一个问题评论中, Jonathan Wakely回应了我的陈述:

您永远不需要显式移动局部变量函数返回值.这是隐含的举动

- >

...永远不要说永远......如果局部变量与返回类型的类型不同,则需要显式移动,例如std::unique_ptr<base> f() { auto p = std::make_unique<derived>(); p->foo(); return p; },但如果类型相同,则可能会移动...

所以有时我们可能不得不在返回时移动局部变量.

这个例子

std::unique_ptr<base> f() { 
  auto p = std::make_unique<derived>();
  p->foo(); 
  return p; 
}
Run Code Online (Sandbox Code Playgroud)

很好,因为它给出了编译错误

> prog.cpp:10:14: error: cannot convert ‘p’ from type
> ‘std::unique_ptr<derived>’ to type ‘std::unique_ptr<derived>&&’
Run Code Online (Sandbox Code Playgroud)

但我想知道是否有一个很好的机会来检测这一般 - 这是这里的语言规则或unique_ptr ??

c++ return implicit-conversion move-semantics c++11

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

为什么要移动语义?

让我先说一下,我已经阅读了一些有关移动语义的问题.这个问题不是关于如何使用移动语义,而是询问它的目的是什么 - 如果我没有弄错,我不明白为什么需要移动语义.

背景

我正在实施一个沉重的类,为了这个问题的目的,它看起来像这样:

class B;

class A
{
private:
    std::array<B, 1000> b;
public:
    // ...
}
Run Code Online (Sandbox Code Playgroud)

在制作移动赋值运算符的时候,我意识到我可以通过将b成员更改为std::array<B, 1000> *b;- 来进行显着优化- 然后移动可能只是删除和指针交换.

这引出了以下想法:现在,不应该所有非原始类型的成员都指向加速移动(在[1] [2]下面更正)(有一种情况应该是内存不应该是动态分配,但在这些情况下,优化运动不是问题,因为没有办法这样做)?

这里是我有以下实现的地方 - 为什么创建一个A真正只包含指针的类,b因此当我可以简单地创建指向整个A类本身的指针时,以后交换更容易.显然,如果客户端期望移动速度明显快于复制速度,则客户端应该可以使用动态内存分配.但在这种情况下,为什么客户端不仅动态分配整个A类?

问题

客户端是否已经利用指针来完成移动语义给我们的一切?如果是这样,那么移动语义的目的是什么?

移动语义:

std::string f()
{
    std::string s("some long string");
    return s;
}

int main()
{
    // super-fast pointer swap!
    std::string a = f();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

指针:

std::string *f()
{
    std::string *s = new std::string("some long string"); …
Run Code Online (Sandbox Code Playgroud)

c++ move-semantics c++11

18
推荐指数
4
解决办法
2665
查看次数

为什么我不能在C++ 14中移动lambda中的std :: unique_ptr?

我想在lambda中传递一个原始指针,但我不希望它被泄露,如果没有调用lambda.它看起来像这样:

void Clean(std::unique_ptr<int>&& list);

void f(int* list) {
  thread_pool.Push([list = std::unique_ptr<int>(list) ] {
    Clean(std::move(list));  // <-- here is an error.
  });
}
Run Code Online (Sandbox Code Playgroud)

我在Clang 3.7.0中收到错误:

错误:将类型'unique_ptr <[2*...]>'的引用绑定到类型'unique_ptr <[2*...]>'的值会丢弃限定符

但是我没有看到任何限定词,尤其是掉线.

另外,我在邮件列表上找到了类似的报告,但没有回答.


我应该如何修改我的代码,以便编译并按语义按预期工作?

c++ lambda move-semantics c++14

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

为什么在返回从函数返回类型派生的类型的本地对象时,不会选择移动构造函数?

以下代码被ClangGCC(主干版本)拒绝:

#include <memory>

struct Base 
{
    Base() = default; 
    Base(Base const&) = delete;
    Base(Base&&) = default;
};

struct Derived : Base
{
    Derived() = default; 
    Derived(Derived const&) = delete;
    Derived(Derived&&) = default;
};    

auto foo()
    -> Base
{
    Derived d;    
    return d;   // ERROR HERE
}
Run Code Online (Sandbox Code Playgroud)

导致以下错误:

prog.cc: In function 'Base foo()': prog.cc:21:12: error: use of deleted function 'Base::Base(const Base&)'
     return d;
            ^
Run Code Online (Sandbox Code Playgroud)

根据[class.copy]/32:

当满足复制/移动操作的省略标准时,但不满足异常声明,并且要复制的对象由左值指定,或者当返回语句中的表达式是(可能带有括号的)id-时表达式,用于在最内层封闭函数或lambda-expression的body或parameter-declaration-clause中声明的具有自动存储持续时间的对象,首先执行重载决策以选择复制的构造函数,就像对象由rvalue指定一样

如果上面的句子意味着被解析为(copy elision criteria met && lvalue) …

c++ return language-lawyer compiler-bug move-semantics

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

`pair :: operator =(pair &&)`错误与`auto&`推导移动操作 - libstdc ++回归?

鉴于此计划:

struct Val
{
    Val() = default;
    Val(Val&&) = default;
    auto& operator=(Val&&);
};

/* PLACEHOLDER */

auto& Val::operator=(Val&&) { return *this; }   
Run Code Online (Sandbox Code Playgroud)

/* PLACEHOLDER */用...... 代替

int main()
{
    std::vector<std::pair<int, Val>> v;
    v.emplace(std::begin(v), 0, Val{});
}
Run Code Online (Sandbox Code Playgroud)

...成功编译:

  • g ++ 6.2.0
  • g ++ 6.3.0
  • g ++ 7.0.1(主干)

  • clang ++ 3.9.1

  • clang ++ 5.0.0(HEAD)

在wandbox上


/* PLACEHOLDER */用...... 代替

template <typename TVec>
void a(TVec& v)
{
    v.emplace(std::begin(v), 0, Val{});
}

int main()
{
    std::vector<std::pair<int, Val>> v;
    a(v);
}
Run Code Online (Sandbox Code Playgroud)

...成功编译:

  • g …

c++ libstdc++ language-lawyer move-semantics c++14

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

移动lambda时为什么不调用移动构造函数?

我正在尝试编译以下代码:

#include <utility>

struct C2 {
        C2() = default;
        C2(C2 const&) = delete;
        C2(C2&&) = default;
};

int main() {
        C2 p2;
        ([p2_1{ std::move(p2) }]() {
                auto p2_2 = std::move(p2_1); // <---
        })();
        return 0;
}
Run Code Online (Sandbox Code Playgroud)

但是,这不会编译并给出一个错误,即赋值p2_2为调用已删除的函数,即复制构造函数.请注意,搬迁p2_1很好.为什么这不使用移动构造函数?

c++ lambda move-semantics c++11

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