最近我从cppreference中读到了一个例子.../vector/emplace_back:
struct President
{
std::string name;
std::string country;
int year;
President(std::string p_name, std::string p_country, int p_year)
: name(std::move(p_name)), country(std::move(p_country)), year(p_year)
{
std::cout << "I am being constructed.\n";
}
Run Code Online (Sandbox Code Playgroud)
我的问题:这std::move真的需要吗?我的观点是,这p_name不是在构造函数体中使用,所以,也许,语言中有一些规则默认使用移动语义?
将std :: move初始化列表添加到每个重要成员(例如std::string,std::vector)会非常烦人.想象一下用C++ 03编写的数百个KLOC项目 - 我们是否应该添加到处std::move?
这个问题:move-constructor-and-initialization-list答案说:
作为一个黄金法则,无论何时你通过右值引用来获取内容,你需要在std :: move中使用它,并且每当你通过通用引用(即用&&推导出模板化类型)时,你需要在std ::里面使用它向前
但我不确定:通过价值而不是普遍的参考?
[UPDATE]
使我的问题更清楚.构造函数参数可以被视为XValue - 我的意思是到期值?
在这个例子AFAIK我们不使用std::move:
std::string getName()
{
std::string local = "Hello SO!";
return local; // std::move(local) is not needed nor …Run Code Online (Sandbox Code Playgroud) c++ language-lawyer initialization-list move-semantics c++11
在C++ 98中,C++编译器可以通过成员方式复制自动生成复制构造函数和复制赋值运算符,例如
struct X {
std::string s;
std::vector<int> v;
int n;
};
Run Code Online (Sandbox Code Playgroud)
编译器使用成员方式复制自动生成复制构造函数和复制赋值运算符X.
但是,C++ 11中的移动语义如何改变?
是否自动生成移动 构造函数和移动 赋值运算符 ,如复制构造函数和复制赋值运算符?
是否存在不自动生成移动操作的情况?
考虑以下程序:
#include <vector>
#include <iostream>
class A {
int x;
public:
A(int n) noexcept : x(n) { std::cout << "ctor with value\n"; }
A(const A& other) noexcept : x(other.x) { std::cout << "copy ctor\n"; }
A(A&& other) noexcept : x(other.x) { std::cout << "move ctor\n"; }
~A() { std::cout << "dtor\n"; } // (*)
};
int main()
{
std::vector<A> v;
v.emplace_back(123);
v.emplace_back(456);
}
Run Code Online (Sandbox Code Playgroud)
如果我运行该程序,我会得到(GodBolt):
ctor with value
ctor with value
move ctor
dtor
dtor
dtor
Run Code Online (Sandbox Code Playgroud)
……这符合我的预期。但是,如果在线(*)我将析构函数标记为可能抛出,那么我会 …
今晚我一直在看一些我过去几天一直在研究的代码,并开始阅读移动语义,特别是std :: move.我有几个问题要求专业人士确保我走正确的道路而不做任何愚蠢的假设!
首先:
1)最初,我的代码有一个返回大向量的函数:
template<class T> class MyObject
{
public:
std::vector<T> doSomething() const;
{
std::vector<T> theVector;
// produce/work with a vector right here
return(theVector);
}; // eo doSomething
}; // eo class MyObject
Run Code Online (Sandbox Code Playgroud)
鉴于"theVector"在这个和"扔掉"中是暂时的,我将该函数修改为:
std::vector<T>&& doSomething() const;
{
std::vector<T> theVector;
// produce/work with a vector right here
return(static_cast<std::vector<T>&&>(theVector));
}; // eo doSomething
Run Code Online (Sandbox Code Playgroud)
它是否正确?这样做有什么陷阱吗?
2)我在一个函数中注意到它返回std::string它自动调用移动构造函数.调试返回字符串(thankyou,Aragorn),我注意到它称为显式移动构造函数.为什么有一个字符串类而不是矢量?
我没有必要对此函数进行任何修改以利用移动语义:
// below, no need for std::string&& return value?
std::string AnyConverter::toString(const boost::any& _val) const
{
string ret;
// convert here
return(ret); // No …Run Code Online (Sandbox Code Playgroud) 我想填充std :: vector(或其他一些STL容器):
class Foo {
public:
Foo(int _n, const Bar &_m);
private:
std::vector<Foo> fooes_;
}
Run Code Online (Sandbox Code Playgroud)
1.好看的ctor,性能昂贵
std::vector<Foo> get_vector(int _n, const Bar &_m) {
std::vector<Foo> ret;
... // filling ret depending from arguments
return ret;
}
Foo::Foo(int _n, const Bar &_m) : fooes_(get_vector(_n, _m) {}
Run Code Online (Sandbox Code Playgroud)
2.性能更好,看起来更糟糕
void fill_vector(int _n, const Bar &_m, std::vector<Foo> &_ret) {
... // filling ret depending from arguments
}
Foo::Foo(int _n, const Bar &_m) { fill_vector(_n, _m, fooes_); }
Run Code Online (Sandbox Code Playgroud)
是否可以get_vector使用C++ 0x(移动语义功能等)重写第一个示例中的函数以避免冗余复制和构造函数调用?
我想知道在C++ 11中我还需要在参数中使用const引用.我不完全理解移动语义,但我认为这是一个合法的问题.此问题仅适用于const引用替换正在进行的副本而仅需要"读取"该值(例如const成员函数的使用)的情况.
通常我会写一个(成员)函数,如下所示:
#include <vector>
template<class T>
class Vector {
std::vector<T> _impl;
public:
void add(const T& value) {
_impl.push_back(value);
}
};
Run Code Online (Sandbox Code Playgroud)
但是我认为可以安全地假设编译器会使用移动语义来优化它,如果我这样写它并且class Tofcourse实现了一个移动构造函数:
#include <vector>
template<class T>
class Vector {
std::vector<T> _impl;
public:
void add(T value) {
_impl.push_back(value);
}
};
Run Code Online (Sandbox Code Playgroud)
我对吗?如果是这样,假设它可以在任何情况下使用是否安全?如果没有,我想知道哪个.这将使生活变得更加容易,因为我不必为基本类型实现类专门化,例如,它看起来更清晰.
我试图理解移动语义,右值引用std::move等等.我一直试图通过搜索本网站上的各种问题来解决,如果需要复制,为什么传递const std::string &name+ _name(name)不如std::string name+ + _name(std::move(name)).
如果我理解正确,下面需要一个副本(通过构造函数)加上一个移动(从临时到成员):
Dog::Dog(std::string name) : _name(std::move(name)) {}
Run Code Online (Sandbox Code Playgroud)
替代(和老式)方法是通过引用传递它并将其复制(从引用到成员):
Dog::Dog(const std::string &name) : _name(name) {}
Run Code Online (Sandbox Code Playgroud)
如果第一种方法需要复制并同时移动两种方法,而第二种方法只需要一个副本,那么第一种方法如何首选,在某些情况下更快?
据我所知,添加移动语义的目的之一是通过调用特殊构造函数来复制"临时"对象来优化代码.例如,在这个答案中我们看到它可以用来优化这些string a = x + y东西.因为x + y是一个rvalue表达式,所以我们只能复制指向字符串的指针和字符串的大小,而不是深度复制.但正如我们所知,现代编译器支持返回值优化,因此不使用移动语义,我们的代码根本不会调用复制构造函数.
为了证明这一点,我写了这段代码:
#include <iostream>
struct stuff
{
int x;
stuff(int x_):x(x_){}
stuff(const stuff & g):x(g.x)
{
std::cout<<"copy"<<std::endl;
}
};
stuff operator+(const stuff& lhs,const stuff& rhs)
{
stuff g(lhs.x+rhs.x);
return g;
}
int main()
{
stuff a(5),b(7);
stuff c = a+b;
}
Run Code Online (Sandbox Code Playgroud)
在VC++ 2010中执行它并在优化模式下执行g ++后,我得到空输出.
它是什么样的优化,如果没有它,我的代码仍然可以更快地运行?你能解释一下我的理解错误吗?
可以说我们有以下代码:
std::vector<int> f()
{
std::vector<int> y;
...
return y;
}
std::vector<int> x = ...
x = f();
Run Code Online (Sandbox Code Playgroud)
看来编译器有两种方法:
(a)NRVO:Destruct x,然后构造f()代替x.
(b)移动:在temp空间中构造f(),将f()移动到x,destruct f().
根据标准,编译器是否可以自由使用这两种方法?
c++ optimization move-semantics return-value-optimization c++11
是否std::is_move_constructible<T>::value == true暗示T有一个可用的移动构造函数?如果是这样,它的默认行为是什么?
考虑以下情况:
struct foo {
int* ptr;
};
int main() {
{
std::cout << std::is_move_constructible<foo>::value << '\n';
foo f;
f.ptr = (int*)12;
foo f2(std::move(f));
std::cout << f.ptr << ' ' << f2.ptr << '\n';
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出是:
1
0000000C 0000000C
Run Code Online (Sandbox Code Playgroud)
我认为那f.ptr应该是nullptr.所以在这种情况下,
f2移动构建?(我正在使用VS11.)
移动构造函数的默认行为与复制构造函数相同,是否正确?如果这是真的,
foo f2(std::move(f));当我宣布一个时,似乎调用了copy ctor,参见:
struct foo {
int* ptr;
foo() {}
foo(const foo& other) {
std::cout << …Run Code Online (Sandbox Code Playgroud)