C++ 您是应该将自动副本移动到成员中还是将其保留?

C++ 您是应该将自动副本移动到成员中还是将其保留?,c++,c++11,move-semantics,C++,C++11,Move Semantics,如果要在类中存储某个对象的副本,如下所示: struct S { S(std::vector<int> v); private: std::vector<int> m; // gonna store v in here }; 结构{ S(std::vectorv); 私人: std::vector m;//要在这里存储v吗 }; 我听说您应该让编译器通过按值获取v来为您创建副本,因为它有时可以更有效地执行此操作。但是,在构造函数的成员初始化列表中,是否

如果要在类中存储某个对象的副本,如下所示:

struct S {
    S(std::vector<int> v);
private:
    std::vector<int> m; // gonna store v in here
};
结构{
S(std::vectorv);
私人:
std::vector m;//要在这里存储v吗
};

我听说您应该让编译器通过按值获取
v
来为您创建副本,因为它有时可以更有效地执行此操作。但是,在构造函数的成员初始化列表中,是否应使用
v
std::move(v)
初始化
m
?如果
v
类型是仅移动类型,该怎么办?(在后一种情况下,我假设您必须使用
move

如果它只是move,那么是的,您最好的做法是按值获取参数,然后移动

当v的类型可以是可复制的或可移动的时,我会将“最佳实践”的状态描述为某种流动性,目前有不同的思想流派。但我认为,这正被接受为编写最佳移动感知构造函数(如您所需)的方法

我会说,做你在这里所做的,是的,使用move cast从右值初始化成员

使用构造函数时,请尝试利用复制省略。例如,这:

struct S {
    S(std::vector<int> v) : m(std::move(v)) {}
private:
    std::vector<int> m;
};

std::vector<int> create_vector()
{
    std::vector<int> vec = // initialisation stuff

   return vec;
}

int main()
{
    S instance_of_s{create_vector()};
    return 0;
}
结构{
S(std::vector v):m(std::move(v)){}
私人:
std::向量m;
};
std::vector create_vector()
{
std::vector vec=//初始化内容
返回向量;
}
int main()
{
_{create_vector()}的S实例_;
返回0;
}
。。。理想情况下,由于各种复制省略,不应复制任何内容。当然,这取决于编译器

这里有一个例子来说明这一点

#include <iostream>
#include <memory>
#include <vector>

using namespace std;

class VectorWrapper
{
public:
    VectorWrapper() : vec(){}

    VectorWrapper(const VectorWrapper& other) : vec(other.vec){ cout << "COPY" << endl; }

    VectorWrapper(VectorWrapper&& other) : vec(move(other.vec)){ cout << "MOVE" << endl; }

private:
    vector<int> vec;
};

struct S 
{
    S(VectorWrapper v) : m(move(v)) {}
private:
    VectorWrapper m;
};

int main()
{
    S instance_of_s{VectorWrapper()};
    return 0;
}
#包括
#包括
#包括
使用名称空间std;
类向量包装器
{
公众:
VectorWrapper():vec(){}

VectorWrapper(const-VectorWrapper&other):vec(other.vec){cout如果它是move-only,那么是的,您最好的做法是按值获取参数,然后移动

当v的类型可以是可复制的或可移动的时,我会将“最佳实践”的状态描述为某种流动性,目前有不同的思想流派。但我认为,这正被接受为编写最佳移动感知构造函数的方法,如您所需

我会说,做你在这里所做的,是的,使用move cast从右值初始化成员

使用构造函数时,请尝试利用复制省略。例如:

struct S {
    S(std::vector<int> v) : m(std::move(v)) {}
private:
    std::vector<int> m;
};

std::vector<int> create_vector()
{
    std::vector<int> vec = // initialisation stuff

   return vec;
}

int main()
{
    S instance_of_s{create_vector()};
    return 0;
}
结构{
S(std::vector v):m(std::move(v)){}
私人:
std::向量m;
};
std::vector create_vector()
{
std::vector vec=//初始化内容
返回向量;
}
int main()
{
_{create_vector()}的S实例_;
返回0;
}
…由于各种复制省略,理想情况下不应复制任何内容。但当然,这取决于编译器

这里有一个例子来说明这一点

#include <iostream>
#include <memory>
#include <vector>

using namespace std;

class VectorWrapper
{
public:
    VectorWrapper() : vec(){}

    VectorWrapper(const VectorWrapper& other) : vec(other.vec){ cout << "COPY" << endl; }

    VectorWrapper(VectorWrapper&& other) : vec(move(other.vec)){ cout << "MOVE" << endl; }

private:
    vector<int> vec;
};

struct S 
{
    S(VectorWrapper v) : m(move(v)) {}
private:
    VectorWrapper m;
};

int main()
{
    S instance_of_s{VectorWrapper()};
    return 0;
}
#包括
#包括
#包括
使用名称空间std;
类向量包装器
{
公众:
VectorWrapper():vec(){}

VectorWrapper(const-VectorWrapper&other):vec(other.vec){cout平均而言,一个重载的最佳方式是按值然后移动。讨论它。如果按值获取参数,您已经有了一个副本。因此无需再次复制它(就像
m(v)
那样)。
m(std::move(v))
也不意味着移动,但它会移动(如果可能)。@DyP但问题是,如果按值获取参数,您可能没有副本,对吗?它可能会被删除或移动?我想知道是否同样的事情也适用于初始化成员。副本只能在对象生命周期结束时从对象中删除(在
返回
语句等中的临时语句)。此外,从语义上讲,你有一个副本/一个独立的对象。复制省略确实允许忽略复制的副作用,但
v
仍然是你的对象,除非你允许,否则没有其他人可以访问它。平均而言,一个重载的最佳方法是通过值然后移动。讨论它。如果你不允许,你已经有了副本按值获取参数。因此无需再次复制它(正如
m(v)
所做的那样)。
m(std::move(v))
也不意味着移动,但它会移动(如果可能)。@DyP但问题是,如果按值获取参数,您可能没有副本,对吗?它可能会被删除或移动?我想知道是否同样的事情也适用于初始化成员。副本只能在对象生命周期结束时从对象中删除(在
return
语句等中的临时对象)。此外,从语义上讲,您有一个副本/一个独立的对象。复制省略确实允许忽略复制的副作用,但
v
仍然是您的对象,除非您允许,否则其他人无权访问它。