我想将存储在未分类矢量中的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)
我希望意图清楚.
更新:我的算法不允许就地排序.如果今天有人感觉很好(我没有问,请参阅上面的问题),请随意为这种情况实施并告诉我.我真的需要"按移动排序".我真的不明白为什么移动会是昂贵得多.
继我对此做出的评论之后:
将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有必要吗?
行为编译器是否依赖?
http://www.drdobbs.com/cpp/practical-c-error-handling-in-hybrid-env/197003350?pgno=4
在本文中,Herb Sutter解释说,抛出异常需要异常的副本,因为它是作为临时创建的,因此使用a std::auto_ptr来绕过副本开销.根据C++ 11中提供的移动语义,这仍然是必要的吗?
请考虑以下代码:
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容量是否与原始容量相同?或者断言触发器?
在对另一个问题的评论中, 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 ??
让我先说一下,我已经阅读了一些有关移动语义的问题.这个问题不是关于如何使用移动语义,而是询问它的目的是什么 - 如果我没有弄错,我不明白为什么需要移动语义.
我正在实施一个沉重的类,为了这个问题的目的,它看起来像这样:
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) 我想在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*...]>'的值会丢弃限定符
但是我没有看到任何限定词,尤其是掉线.
另外,我在邮件列表上找到了类似的报告,但没有回答.
我应该如何修改我的代码,以便编译并按语义按预期工作?
#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) …
鉴于此计划:
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 ++ 7.0.1(主干)
clang ++ 3.9.1
/* 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)
...成功编译:
我正在尝试编译以下代码:
#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++ ×10
move-semantics ×10
c++11 ×7
c++14 ×2
lambda ×2
return ×2
compiler-bug ×1
libstdc++ ×1
stdvector ×1
unique-ptr ×1