标签: move-semantics

与move constuctor配对时发生意外的析构函数调用

以下代码是在Visual Studio 2012 Express for Windows Desktop中编译和运行的,作为学习练习.

#include <cstdio>

class X
{
public:
    X()  { printf("default constructed\n"); }
    ~X() { printf("destructed\n");}
    X(const X&) { printf("copy constructed\n"); }
    X(X&&) { printf("move constructed\n"); }
    X & operator= (const X &) { printf("copy assignment operator\n"); }
};

X A() {
    X x;
    return x;
}

int main() {
    {
        A();
    }
    std::getchar();
}
Run Code Online (Sandbox Code Playgroud)

在禁用编译器优化(/ Od)的情况下编译时,结果输出表明析构函数被调用两次.考虑到只构造了一个对象,这是一个问题.为什么析构函数被调用两次?如果班级管理自己的资源,这不是一个问题吗?

default constructed
move constructed
destructed
destructed   <<< Unexpected call 
Run Code Online (Sandbox Code Playgroud)

我尝试了几个实验来尝试解释输出,但最终这些并没有导致任何有用的解释.

实验1:在使用优化(/ O1或/ O2)编译相同代码时,结果输出为:

default constructed
destructed …
Run Code Online (Sandbox Code Playgroud)

c++ visual-c++ move-semantics c++11 visual-studio-2012

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

我应该何时提供移动感知过载?

如果我有一个管理一些动态内存的类(例如矢量类型)并且它已经有一个移动构造函数,为函数提供移动感知重载是否有意义,或者移动构造函数是否有意义照顾它?

例如,我应该使用Class&&变量重载哪些(如果有的话):

// the move-aware overload for all of these would be
// void FuncX(Class&&);

void Func1(Class);

void Func3(Class&); // doesn't make a local copy
void Func4(Class&); // makes a local copy

void Func5(Class const);

void Func7(Class const&); // doesn't make a local copy
void Func8(Class const&); // makes a local copy
Run Code Online (Sandbox Code Playgroud)

他们中的任何一个都失去了优化机会,因为我没有提供移动感知变体吗?

c++ move-semantics c++11

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

为什么这个移动构造函数如此贪婪?

我有以下代码:

#include <iostream>

class foo_class {
    std::string value;
public:
    foo_class(const foo_class& v) : value{v.value} {
        std::cout << "copy constructor" << std::endl;
    }

    foo_class(foo_class&& v) : value{std::move(v.value)} {
        std::cout << "move constructor" << std::endl;
    }

    ~foo_class() {
        std::cout << "destructor" << std::endl;
    }

    foo_class(std::string v) : value{std::move(v)} {
        std::cout << "type constructor" << std::endl;
    }
};

struct Data {
    foo_class a;
    foo_class b;
};

int main() {
    std::string c = "3";
    Data x{c,c+"3"};
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

重要的是,我使用GCC和Clang(分别为4.8.2和3.4)和标志-fno-elide-constructors进行编译,因此我们不会忽略复制/移动构造函数.

执行结果如下: …

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

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

为什么std :: vector fill构造函数不能启用安置?

当我需要创建一个非可复制构造对象的数组时,我偶尔会遇到这种情况.例如:

std::vector<std::thread> thread_pool(NUM_CORES, std::thread(some_function));
Run Code Online (Sandbox Code Playgroud)

那会很方便.但是,std::vector填充构造函数似乎没有任何R值支持.它被定义为:

 vector( 
         size_type count, 
         const T& value,
         const Allocator& alloc = Allocator()
 );
Run Code Online (Sandbox Code Playgroud)

但是拥有以下内容会非常方便:

 vector( 
         size_type count, 
         T&& value,
         const Allocator& alloc = Allocator()
 );
Run Code Online (Sandbox Code Playgroud)

然后向量可以在内部分配必要的缓冲区大小,并使用placement new移动构造每个元素.

但是...... C++ 11标准(显然甚至是C++ 14标准)都没有提供这种功能.那么,现在 - 当我有一个线程向量时,我不得不说:

std::vector<std::unique_ptr<std::thread>> thread_pool(NUM_CORES);
/* now loop over vector and initialize elements one by one */
Run Code Online (Sandbox Code Playgroud)

有什么理由将这种能力排除在外吗?有危险吗?还是我看不到的一些问题?

vector move-semantics c++11

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

为什么选择复制构造函数而不是移动构造函数

我正在查看以下有关移动构造函数/赋值的示例:https: //msdn.microsoft.com/en-us/library/dd293665.aspx

我通过添加交换函数来修改它,以简化移动构造函数/赋值和复制赋值:

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

class MemoryBlock
{
public:

    // Simple constructor that initializes the resource.
    explicit MemoryBlock(size_t length)
        : _length(length)
        , _data(new int[length])
    {
        std::cout << "In MemoryBlock(size_t). length = "
                  << _length << "." << std::endl;
    }

    // Destructor.
    ~MemoryBlock()
    {
        std::cout << "In ~MemoryBlock(). length = "
                  << _length << ".";

        if (_data != nullptr)
        {
            std::cout << " Deleting resource.";
            // Delete the resource.
            delete[] _data;
        } …
Run Code Online (Sandbox Code Playgroud)

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

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

c ++ 11,打捞一套

是否有一种干净的方式来移动它的元素?就像是:

set<A> s {...};
vector<A> v;
for (const A& a : s)
    v.push_back(move(const_cast<A&>(a)));
s.clear(); //undefined behavior?
Run Code Online (Sandbox Code Playgroud)

c++ set move-semantics

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

如何获取右值参考参数并将其传递给其他地方?

我是一个相当称职的C++用户(不是一个完整的菜鸟).我有一个充当资源句柄的类.这个类有一个移动构造函数和复制construtor被删除是有道理的:

struct Foo {

  Foo (int i) : // For sake of example.
    x(i)
  {}

  Foo (Foo && f) :
    x(f.x)
  {
    f.x = 0; // 0 is special and means "moved from".
  }

  Foo (const Foo & f) = delete;

private:
  int x;
};
Run Code Online (Sandbox Code Playgroud)

多年来我一直以货物崇拜的方式做这件事而且工作正常.现在我正试图用我的C++ 11用法加强装备.

我还有一个类,它保持了vectorFoo:

struct Bar { // (Constructor added below)
  std::vector<Foo> foos;
};
Run Code Online (Sandbox Code Playgroud)

我想写一个构造函数,用于Bar调用者传入的位置vector<Foo>.我想将调用者提供的整个向量移入Bar.foos.我想通过使构造函数参数vector<Foo>&&而不是普通参数使调用者明确vector<Foo>&.这样,调用者必须std::move将vector插入到构造函数中.

int main (int …
Run Code Online (Sandbox Code Playgroud)

c++ move-semantics c++11

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

不合理地删除了移动构造函数

我有一个名为explicitely删除的复制构造函数的类,比方说,NonCopyable.然后是一个类型Base1成员的类NonCopyable.而另一类Base2Base1父.最后 - Derivative父母是一个阶级Base2.

由于NonCopyable是不可复制的,因此很明显Base1,Base2并且Derivative也是不可复制的.但似乎还有移动构造函数(和赋值运算符)已删除.

在这里测试一下:

以下行给出了这些错误:
Derived d1, d2 = std::move(d1);

GCC: 'Derived :: Derived(Derived &&)'被隐式删除,因为默认定义是不正确的:class Derived:
其余的错误只是声称Base1Base2复制ctors被隐式删除,这并不奇怪

MSVC:错误C2280:'Derived :: Derived(const Derived&)':尝试引用已删除的函数

在提供的链接中,还有注释行,它们给出了类似的错误.请取消注释以查看我想向您展示的更多错误(例如,未remove_if注释它会抱怨删除移动(在GCC上) /复制(在MSVC上)分配操作员).
我想要实现的是使Derivative(及其基础)可移动,但不可复制.

我正在使用Visual Studio 2015并获得与我提供的msvc链接完全相同的错误,但我不确定在rextester.com上使用什么版本的MSVC进行编译.

我也是应@Richard Critten的要求粘贴代码的:

    class NonCopyable
    {
    public:
       NonCopyable() { }
       NonCopyable(const NonCopyable &) = delete;
       NonCopyable & operator=(const …
Run Code Online (Sandbox Code Playgroud)

c++ inheritance move-semantics c++11

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

如何将动态分配的数据从对象移动到另一个对象?

我有一个用RAII编写的Array类(为了这个例子的目的,超简化):

struct Array
{
    Array(int size) {
        m_size = size;
        m_data = new int[m_size];
    }

    ~Array() {
        delete[] m_data;
    }

    int* m_data = nullptr;
    int  m_size = 0;
};
Run Code Online (Sandbox Code Playgroud)

然后我有一个函数,它接受一个数组的引用并对它进行一些操作.我使用临时数组temp来执行处理,因为有几个原因我不能直接使用引用.完成后,我想将数据从临时数据传输到真实数据:

void function(Array& array)
{
    Array temp(array.m_size * 2);

    // do heavy processing on `temp`...

    array.m_size = temp.m_size;
    array.m_data = temp.m_data;
}
Run Code Online (Sandbox Code Playgroud)

显而易见的问题是temp在函数末尾超出范围:它的析构函数被触发,而后者又删除了内存.这种方式array将包含不存在的数据.

那么将数据所有权从一个对象"移动"到另一个对象的最佳方法是什么?

c++ memory temporary move-semantics c++11

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

Movable but non-copyable objects: passing by value vs by reference?

Considering only objects that are movable but non-copyable (e.g., std::thread or std::unique_ptr), I want to transfer the ownership of the resource such an object contains by passing it as an argument to a constructor. I'm comparing two approaches: the constructor taking the object by value vs. by rvalue reference.

As an example with std::thread, consider the following class Value whose constructor takes an std::thread by value:

#include <thread>
#include <utility>

struct Value {
   Value(std::thread th): th_(std::move(th)) …
Run Code Online (Sandbox Code Playgroud)

c++ ownership-semantics parameter-passing move-semantics c++11

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