我正在尝试获取rvalue
此类的一个实例:
#include <iostream>
#define msg(x) std::cout << x " constructor\n"
struct X {
int i;
X(int i) : i(i) {msg("X");}
X(const X& x) : i(x.i) {std::cout << "X copy\n";}
X(X&& x) {std::swap(i, x.i); std::cout << "X move\n";}
};
x
进入这个类的实例变量:
struct A {
X x;
A(X x) : x(x) {msg("A");}
};
像这样:
int main() {
A a(X(1));
std::cout << a.x.i << "\n\n";
}
没有任何复制或移动。
根据这些参考资料,
- http://thbecker.net/articles/rvalue_references/section_01.html
- http://www.slideshare.net/oliora/hot-11-2-new-style-arguments-passing
还有很多关于 SO 的帖子(所以请在标记为重复之前阅读到最后),我应该依赖复制省略,如果我通过值传递应该满足其条件。请注意,需要两个复制省略,即:
constructor call -> constructor local variable -> instance variable
关闭复制省略时可以看到(使用 编译g++-4.8 -std=c++11 -fno-elide-constructors
):
X constructor
X move
X copy
A constructor
1
所以有一个move
步骤和一个copy
步骤,如果我打开复制省略(用 编译),这两个步骤都应该消失g++-4.8 -std=c++11 -O3
:
X constructor
X copy
A constructor
1
糟了,还剩copy
一步!
我可以通过任何其他变体std::move()
或std::forward
传递为更好rvalue-reference
吗?
struct B {
X x;
B(X x) : x(std::move(x)) {msg("B");}
};
struct C {
X x;
C(X x) : x(std::forward<X>(x)) {msg("C");}
};
struct D {
X x;
D(X&& x) : x(std::move(x)) {msg("D");}
};
int main() {
B b(X(2));
std::cout << b.x.i << "\n\n";
C c(X(3));
std::cout << c.x.i << "\n\n";
D d(X(4));
std::cout << d.x.i << "\n\n";
}
产生输出:
X constructor
X move
B constructor
2
X constructor
X move
C constructor
3
X constructor
X move
D constructor
4
好的,我把copy
变成了move
,但这并不令人满意!
接下来,我尝试使实例变量x
成为引用X&
:
struct E {
X& x;
E(X x) : x(x) {msg("E");}
};
int main() {
E e(X(5));
std::cout << e.x.i << "\n\n";
}
产生:
X constructor
E constructor
1690870696
馊主意!我摆脱了move
但引用的rvalue
实例x
在我的座位下被破坏了,所以最后一行打印垃圾而不是5
. 两个注意事项:
g++-4.8
没有警告我任何事情,即使有-pedantic -Wall -Wextra
5
程序在编译时打印-O0
所以这个错误可能会在很长一段时间内被忽视!
那么,这是一个没有希望的案例吗?没有:
struct F {
X& x;
F(X& x) : x(x) {msg("F");}
};
int main() {
X x(6);
F f(x);
std::cout << f.x.i << "\n";
}
印刷:
X constructor
F constructor
6
真的吗?没有花哨的新C++11
功能,没有编译器自行决定的复制省略,只是普通的旧 FORTRAN66 样式的传递引用可以满足我的要求,并且可能会表现最好?
所以这是我的问题:
- 有什么办法可以让它工作
rvalues
吗?我错过了任何功能吗? - -reference
lvalue
版本真的是最好的,还是有隐藏的成本?X x(6)
? x
建造后生活会不会带来任何不便f
?- 我可以为使用对
lvalue
外部实例的引用支付数据局部性罚款吗?