标签: move-constructor

为什么移动构造函数需要使用"右值引用"?

例如,以下移动构造函数在没有&&(rvalue引用)的情况下工作:

Obj::Obj(Obj& obj) : elem { obj.elem }, data(obj.data) {

    obj.elem = nullptr;
    obj.data = 0;

}
Run Code Online (Sandbox Code Playgroud)

我真的不明白为什么有必要......

c++ constructor move-constructor c++11

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

依赖隐式声明的移动构造函数是否安全?

这是我获得大部分信息的地方:http://en.cppreference.com/w/cpp/language/move_constructor

显然,这些是隐式生成的移动构造函数的工作条件:

  • 没有用户声明的副本构造函数
  • 没有用户声明的复制赋值运算符
  • 没有用户声明的移动赋值运算符
  • 没有用户声明的析构函数
  • 隐式声明的移动构造函数未定义为已删除
  • 如果存在用户声明的移动构造函数,仍然可以使用关键字强制生成隐式声明的移动构造函数 default

我的问题是:

  1. 依赖隐式自动移动构造函数是否安全?
  2. 如何检查它是否真的有效而不是默认的复制构造函数?
  3. 最后,最重要的是,这是一个好主意,为什么?或者定义自己的总是更好?

我更倾向于遵循三条规则并手动创建析构函数,复制和移动构造函数,以及复制和移动赋值运算符,但我只是对这个隐式运算符感到好奇.

c++ copy move move-constructor c++11

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

作为参数的临时T是否应该在C++ 11中调用T(const T&)或T(T &&)?

所以,代码第一:

#include <iostream>
#include <utility>

struct X{
    int i;
    void transform(){}
    X() :i(0){std::cout<<"default\n";}
    X(const X& src): i(src.i){std::cout<<"copy\n";}
    X(X&& msrc) :i(msrc.i){msrc.i=0;std::cout<<"move\n";}
};

X getTransform(const X& src){
    X tx(src);
    tx.transform();
    return tx;
}

int main(){

    X x1;// default
    X x2(x1); // copy
    X x3{std::move(X{})}; // default then move
    X x41(getTransform(x2)); // copy in function ,then what?
    X x42(std::move(getTransform(x2))); // copy in funciton, then move
    X x51( (X()) );//default, then move? or copy?
      // extra() for the most vexing problem
    X x52(std::move(X())); //default …
Run Code Online (Sandbox Code Playgroud)

c++ temporary-objects move-constructor c++11

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

在移动构造函数的abscence中调用复制构造函数?这是为什么?

我正在阅读C++ 11,我有以下问题.假设我有以下粗略代码

class foo
{
public:
    foo()
    {std::cout << "Regular constructor \n";}

    foo(const foo& a) 
    {std::cout << "Copy constructor \n";}

    foo& operator=(const foo& a) 
    {std::cout << "Copy Assignment operator \n";}

    foo(foo&& a)
    {
        std::cout << "Move constructor \n";
    }

    foo& operator=(foo&& a) 
    {std::cout << "Move Assignment operator \n";}

    int a;
};


foo myfunction()
{
    foo d;
    d.a =120;
    return d;
}
Run Code Online (Sandbox Code Playgroud)

现在,如果我做这样的事情

foo a = myfunction();
Run Code Online (Sandbox Code Playgroud)

我知道将调用move构造函数,因为myfunction()返回一个rvalue类型.现在我注意到如果我从我的类中删除移动构造函数代码,则调用复制构造函数.我的问题是为什么会发生这种情况?如果myfunction的返回类型是foo &&并且复制构造函数接受foo,那么为什么要调用复制构造函数?我正在使用Vs2012.

c++ move-constructor c++11

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

当我取消移动构造函数A(A &&)时,下面的代码段会发生什么?

下面的代码段似乎没问题,我相信声明A a(std::move(b).toA());main()调用隐式声明的类的移动构造函数A,因为A它没有用户定义的复制构造函数,它没有用户定义的复制赋值运算符,它没有用户定义的移动赋值运算符,也没有用户定义的析构函数(参见§12.8/ 9 N4140).但是,当我取消注释下面的移动构造函数时A(A&&) { std::cout << "move A" << '\n'; },我收到了Illegal instruction消息.查看实例.为什么是这样?

#include <iostream>
#include <memory>
class A {
public:
//    A(const A&) { std::cout << "copy A" << '\n'; }
//    A(A&&) { std::cout << "move A" << '\n'; }
    A(std::unique_ptr<int>&& u_ptr) : u_ptr(std::move(u_ptr)) {}
    const int& getInt() { return *u_ptr; }

private:
    std::unique_ptr<int> u_ptr;
};

class B {
public:
    B(int u_ptr) : u_ptr(new …
Run Code Online (Sandbox Code Playgroud)

c++ move-constructor c++11

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

基于unique_ptr的pimpl类中的move构造函数是否需要完整的类型?

如果我使用a unique_ptr<T>来构建一个pimpl类,我理解调用T析构函数的编译器生成的函数需要T是一个完整的类型.但是pimpl类的移动构造函数呢?编译器生成的版本只调用了unique_ptr移动构造函数.该功能不会破坏任何东西.此外,pimpl类生成的移动构造函数是隐式的noexcept,因此它的主体不可能抛出异常,导致它必须退出并销毁unique_ptr子对象.

看起来好像下面的代码应该编译:

#include <memory>

class Widget {                      // has implicit move ctor
  struct Impl;
  std::unique_ptr<Impl> pImpl;
};

int main()
{
  Widget *pw1 = nullptr;

  new Widget(std::move(*pw1));      // call move ctor. Rejected by
}                                   // gcc, clang, and MSVC
Run Code Online (Sandbox Code Playgroud)

正如评论所说,这个代码被所有gcc,clang和MSVC拒绝.每个人抱怨对不完整类型的操作无效.这是标准要求的吗?如果是这样,那是哪一部分

请注意,此处的问题是编译,因此上述代码由于取消引用空pw1指针而未定义的运行时行为无关紧要.出于同样的原因,new在最后一个语句中调用引起的内存泄漏并不重要.

c++ unique-ptr move-constructor c++11

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

move-construct object with placement new

是不是UB移动 - 通过放置新建一个对象?

假设我有这段代码:

class Foo {
public:
    Foo() { foo_ = new int; }
    ~Foo() { delete foo_; }
    Foo(Foo &&f) {
        foo_ = std::swap(f.foo_, foo_);
    }
private:
    int* foo_;
}

void bar() {
    void* pMem = malloc(sizeof(Foo));
    Foo f1;
    // move-construct with placement new:
    new((Foo*)pMem) Foo(std::move(f1)); // f2 in *pMem

    // now f1 will contain a pointer foo_ of undefined value
    // when exiting scope f1.~Foo(){} will exhibit UB trying to delete it
}
Run Code Online (Sandbox Code Playgroud)

如果不明显,f1的成员foo_将在构造第二个foo后通过放置new和move构造得到一个未定义的值(这个未定义的值来自未初始化的Foo f2在其move-constructor中的foo_,因为值是交换的) …

c++ placement-new move-constructor c++11

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

构造函数被解释为函数调用,并且直接跳过了构造函数

我有一个包含4个构造函数的类,函数如下:

using namespace std;

class ABC {
public:
    ABC() {
        cout << "ABC()\n";
    }

    ABC(int) {
        cout << "ABC(int)\n";
    }

    ABC(ABC&) {
        cout << "ABC(&)\n";
    }

    ABC(ABC&&) {
        cout << "ABC(&&)\n";
    }
};


void ff(ABC t) { }
Run Code Online (Sandbox Code Playgroud)

请帮我解释一些对我来说很奇怪的行为(我使用MSVC 2016进行编译):

1)为什么我收到警告C4930:"'ABC a1(ABC(__ cdecl*)(void))':未调用prototyped函数(是一个变量定义?)",使用以下代码:

void main() {
    ABC a1(ABC());
    ff(ABC(5));
}
Run Code Online (Sandbox Code Playgroud)

在执行时,我希望得到以下输出:

ABC()
ABC(&&)
ABC(int)
ABC(&&)
Run Code Online (Sandbox Code Playgroud)

但我真正得到的是

ABC(int)
Run Code Online (Sandbox Code Playgroud)

2)现在,如果我改为

void main() {
    ABC a1(ABC(5));
    ff(ABC(5));
}
Run Code Online (Sandbox Code Playgroud)

没有更多的警告.但在执行时,我期望得到的是

ABC(int)
ABC(&&)
ABC(int)
ABC(&&)
Run Code Online (Sandbox Code Playgroud)

但我真正得到的是

ABC(int)
ABC(int)
Run Code Online (Sandbox Code Playgroud)

3)现在

void main() {
    ABC( ABC() ); …
Run Code Online (Sandbox Code Playgroud)

c++ constructor most-vexing-parse move-constructor

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

移动构造函数没有被调用

我编写了以下代码来演示移动构造。但是即使我使用了 std::move(),也没有调用移动构造函数。有人可以看看这里有什么问题。

#include "point.hpp"
using namespace std;
class point; 
d2point add_point(d2point&& p1, d2point&& p2) 
{ 
 cout << "inside add point function" << endl;
 d2point z;
 z.setX(p1.getX() + p2.getX());
 z.setY(p1.getY() + p2.getY());
 return z;
} 
int main()
{

 d2point x(2,3);
 d2point y(2,3);

 d2point z = add_point(move(x), move(y));
 z.print_point();
 x.print_point();

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

以下是来自point.hpp的代码

using namespace std;
class point
{
private:
int x;
public:
point(){cout << "point default constructor gets called" << endl;}
point(int x){ cout << "point param constructor gets called" …
Run Code Online (Sandbox Code Playgroud)

c++ constructor move-constructor c++11

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

如何在工厂方法之外禁用创建/复制 obj?

我有一个类,它的负载非常重,因此创建/复制/移动此类的实例非常昂贵。由于应用程序完成初始化后它们不会改变,因此无需创建此类的临时对象。我只需要在容器(std::map)中缓存对象,并在需要时提供“常量引用”。

必须强调的一点是,我正在寻找一种解决方案,可以在将对象添加到容器之前避免双重创建或不必要的复制(我不认为像 @getsoubl 提出的解决方案可以解决问题,因为它不会消除双重创建或不必要的复制)。

因此,我想将构造函数方法安排到类主体的“私有/受保护”部分,以禁止在“工厂方法”之外进行任何创建/复制/移动。以下是我的原始解决方案:

class MyClass {
public:
   // methods of the class
   static const MyClass & findObject( int iKey ) {
      auto pair = mapObjects.try_emplace( iKey, iKey );
      if ( pair.second )
         cout << "New object has been created" << endl;

      return pair.first->second;
   };

   // deleted
   MyClass() = delete;
   MyClass( MyClass & ) = delete;
   MyClass( MyClass && ) = delete;
   MyClass( const MyClass & ) = delete;
   MyClass( const MyClass && ) = delete;
   MyClass …
Run Code Online (Sandbox Code Playgroud)

c++ factory factory-pattern move-constructor emplace

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