标签: move-semantics

在什么情况下我应该明确需要实现移动构造函数和移动赋值运算符?

鉴于一个类实际上是可移动的,手动实现移动构造函数和移动类的赋值运算符很快变得乏味.

我想知道什么时候这样做实际上是一个沉重,沉重,过早的优化?

例如,如果一个类只有普通的POD数据或者它们自己有移动构造函数和移动赋值运算符定义的成员,那么我猜测编译器将只是优化该批次的狗屎(在POD的情况下)和否则使用成员的移动构造函数和移动赋值运算符.

但这有保证吗?在什么情况下,我应该想到明确需要实现一个移动构造函数和移动赋值操作符?

编辑:正如他在回答评论下面提到的尼科尔流星锤/sf/answers/697627381/,与Visual Studio 11 Beta版(之前)没有转移构造函数或移动赋值操作符是不断自动生成.参考:http://blogs.msdn.com/b/vcblog/archive/2011/09/12/10209291.aspx

c++ optimization move-semantics c++11

16
推荐指数
2
解决办法
879
查看次数

如果在C++ 11中访问移动的对象,则发出警告

可能重复:
移动对象有什么用处?

在调用std::move并将结果传递给函数之后,通常必须假定稍后访问移动的对象将导致未定义的行为.

是否有工具可以检测这些访问并警告您.例如:

{
  Widget w;
  foo(std::move(w));
  // w may be undefined at this point

  w.doSomething(); // WARN
}
Run Code Online (Sandbox Code Playgroud)

至少,gcc 4.7.2并且clang 3.2-Wall不抱怨.

更新:回顾这个问题,关键点是编译器无法确定对象在移动后是否仍然有效.如果提议N4034:Destructive Move被接受,我希望编译器有更多选项(但只有在移动是破坏性的时候).

c++ warnings move-semantics c++11

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

移动分配和引用成员

具有引用成员变量的类的复制赋值是禁止的,因为您无法重新分配引用.但是移动分配怎么样?我只是尝试了move它,当然,当我只想移动引用本身时,它会破坏源对象:

class C
{
public:
    C(X& x) : x_(x) {}
    C(C&& other) : x_(std::move(other.x_)) {}
    C& operator=(C&& other)
    {
        x_ = std::move(other.x_);
    }
private:
    X& x_;
};

X y;
C c1(y);

X z;
C c2(z);

c2 = c1; // destroys y as well as z
Run Code Online (Sandbox Code Playgroud)

我不应该只是实施移动分配并坚持使用移动构造吗?这swap(C&, C&)很难实现.

c++ move-semantics c++11

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

为什么既没有使用clang声明也没有删除移动构造函数?

考虑以下类.

struct with_copy {
    with_copy() = default;
    with_copy(with_copy const&) {}
    with_copy& operator=(with_copy const&) { return *this; }
};

struct foo {
    with_copy c;
    std::unique_ptr<int> p;
};
Run Code Online (Sandbox Code Playgroud)
  • 是否with_copy有一个拷贝构造函数?是.它是明确定义的.
  • 是否with_copy有一个移动构造函数?不可以.显式复制构造函数阻止生成它.
  • 是否with_copy有删除的移动构造函数?不.没有移动构造函数与删除构造函数不同.删除的移动构造函数会尝试将格式错误而不是退化移动到副本.
  • with_copy复制吗?是.其复制构造函数用于复制.
  • with_copy可移动的?是.它的复制构造函数用于移动.

......现在是棘手的.

  • 是否foo有一个拷贝构造函数?是.它有一个删除的,因为它的默认定义将由于调用unique_ptr已删除的复制构造函数而格式不正确.
  • 是否foo有一个移动构造函数?GCC说是的,clang说没有.
  • 是否foo有删除的移动构造函数?海湾合作委员会和铿锵声说不.
  • foo复制吗?不会.它的复制构造函数被删除.
  • foo可移动的?GCC说是的,clang说没有.

(当考虑赋值而不是构造时,行为类似.)

据我所知,海湾合作委员会是正确的.foo应该有一个移动构造函数,在每个成员上执行移动,在这种with_copy情况下退化为副本.Clang的行为似乎很荒谬:我有一个有两个可移动成员的聚合体,但我的聚合物是一个不可移动的砖块.

谁是对的?

c++ user-defined-functions implicit-declaration move-semantics c++11

16
推荐指数
2
解决办法
1362
查看次数

为什么我要删除移动构造函数并在单例中移动赋值运算符?

我有以下Singleton策略类实现:

template <typename T>
class Singleton
{
    Singleton(){}; // so we cannot accidentally delete it via pointers
    Singleton(const Singleton&) = delete; // no copies
    Singleton& operator=(const Singleton&) = delete; // no self-assignments
    Singleton(Singleton&&) = delete; // WHY?
    Singleton& operator=(Singleton&&) = delete; // WHY?
public:
    static T& getInstance() // singleton
    {
        static T instance; // Guaranteed to be destroyed.
                       // Instantiated on first use.
                       // Thread safe in C++11
        return instance;
    }
};
Run Code Online (Sandbox Code Playgroud)

然后我通过奇怪的重复模板模式(CRTP)使用

class Foo: public Singleton<Foo> // now Foo …
Run Code Online (Sandbox Code Playgroud)

c++ singleton move-semantics c++11

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

允许在单个完整表达式中移动两次

假设一个具有以下原型的功能

template<typename T>    
std::unique_ptr<T> process_object(std::unique_ptr<T> ptr);
Run Code Online (Sandbox Code Playgroud)

该函数可以返回传递给它的对象(移动版本)或完全不同的对象.

使用此函数是合法的C++如下吗?

std::unique_ptr<Widget> pw(new Widget());

pw = process_object(std::move(pw));
Run Code Online (Sandbox Code Playgroud)

如果我没记错的话,有一个C/C++规则禁止在一个完整的表达式中多次修改一个对象.这条规则适用于此吗?如果是的话,有没有办法在一行中以不同的方式表达这个习语?

如果一个人std::unique_ptr被鄙视取代std::auto_ptr怎么办?

c++ sequence-points move-semantics c++11

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

默认定义的移动构造函数的noexcept规则是什么?

特别是std::vector与其相关的是,类型noexcept在可能的情况下是可移动的.

所以在声明= default像in 的移动构造函数时

struct Object1
{
    Object1(Object1 &&other) = default;
};
Run Code Online (Sandbox Code Playgroud)

std::is_nothrow_move_constructible<Object1>::value将是true每个成员(0在这里)Object1是nothrow-move-constructible,这在这里得到解答.

然而,如果仅声明移动复制构造函数,然后= default在以下代码中进行定义,会发生什么?

struct Object2
{
    Object2(Object2 &&other);
};
Object2::Object2(Object2 &&other) = default;
Run Code Online (Sandbox Code Playgroud)

随着G ++ 4.9.2 std::is_nothrow_move_constructible<Object2>::valuefalse,我要纪念这两个声明和定义noexcept,使其true.

现在我感兴趣的是实际规则是什么.特别是因为有效的现代C++中的第22项(Scott Meyers)似乎通过建议像我一样实现了pimpl-idiom移动构造函数来提供错误的建议Object2.

c++ pimpl-idiom move-semantics noexcept c++11

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

如果我将一个本地对象移动到一个函数中,它之后是否仍然有效?

所以,这提供了预期的输出:

void f(std::string&& s)
{
   s += " plus extra";
}

int main(void)
{
   std::string str = "A string";
   f( std::move(str) );
   std::cout << str << std::endl;

   return 0;
}
Run Code Online (Sandbox Code Playgroud)

字符串加上额外的

也就是说,当我在Ideone上运行它时,它可以工作,但它是UB吗?在调用之前和之后添加额外的字符串初始化f没有改变任何东西.

c++ move-semantics c++11

16
推荐指数
3
解决办法
887
查看次数

使用std :: forward的构造函数

据我所知,在C++ 11中有效实现构造函数的两种常用方法是使用其中两种

Foo(const Bar& bar) : bar_{bar} {};
Foo(Bar&& bar)      : bar_{std::move(bar)} {};
Run Code Online (Sandbox Code Playgroud)

或者只是一个时尚的

Foo(Bar bar) : bar_{std::move(bar)} {};
Run Code Online (Sandbox Code Playgroud)

使用第一个选项产生最佳性能(例如,在左值的情况下希望是单个副本,在rvalue的情况下希望单个移动),但是对于N个变量需要2个N重载,而第二个选项只需要一个函数通过左值时的额外动作.

在大多数情况下,这不应该产生太大的影响,但肯定两种选择都不是最佳选择.但是,也可以执行以下操作:

template<typename T>
Foo(T&& bar) : bar_{std::forward<T>(bar)} {};
Run Code Online (Sandbox Code Playgroud)

这样做的缺点是允许可能不需要的类型的变量作为bar参数(这是我确信使用模板专门化很容易解决的问题),但无论如何,性能是最佳的,代码随着变量的数量线性增长.

为什么没有人为此目的使用像forward这样的东西?这不是最优化的方式吗?

c++ move-semantics perfect-forwarding c++11

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

允许从 std::map 的键中窃取资源吗?

在 C++ 中,是否可以从我以后不再需要的地图中窃取资源?更准确地说,假设我有一个std::mapwithstd::string键,我想通过map使用std::move. 请注意,对键的这种写访问会破坏 的内部数据结构(键的顺序),map但之后我不会使用它。

问题:我可以在没有任何问题的情况下执行此操作,还是会导致意外错误,例如在析构函数中出现意外错误,map因为我std::map以非预期的方式访问它?

这是一个示例程序:

#include<map>
#include<string>
#include<vector>
#include<iostream>
using namespace std;
int main(int argc, char *argv[])
{
    std::vector<std::pair<std::string,double>> v;
    { // new scope to make clear that m is not needed 
      // after the resources were stolen
        std::map<std::string,double> m;
        m["aLongString"]=1.0;
        m["anotherLongString"]=2.0;
        //
        // now steal resources
        for (auto &p : m) {
            // according to my IDE, p has type 
            // std::pair<const …
Run Code Online (Sandbox Code Playgroud)

c++ move-semantics

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