- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
不知何故受到 Expression templates and C++11 中表达式模板代码的启发,由 Paul Preney 撰写,我决定测试以下内容:
template<typename T>
struct X
{
X(T t) : t(std::forward<T>(t)) {}
T t;
};
template<typename T>
auto CreateX(T&& t) -> X<decltype(std::forward<T>(t))>
{
return X<decltype(std::forward<T>(t))>(std::forward<T>(t));
}
然后,我用它来生成 X<const vector<int>&>
的实例和 X<vector<int>&&>
如下:
int main()
{
int vec = {1,2,3,4};
auto x1 = CreateX(vec);
auto x2 = CreateX(vector<int>{5,6,7,8});
cout << "x1: "; for(auto x : x1.t) cout << x << " "; cout << endl;
cout << "x2: "; for(auto x : x2.t) cout << x << " "; cout << endl;
}
输出是:
x1: 1 2 3 4
x2: 0 0 33 0 0 0 7 8
这表明临时的生命周期 vector<int>{5,6,7,8}
未被扩展,右值引用成员 X::t
绑定(bind)到其他东西。
好的,从这个答案What is the lifetime of the class data member which const reference to a rvalue? ,我知道这是预期的行为。
但是,这里的问题是:Paul Preney 在 Expression templates and C++11 中的代码有何不同?只要右值引用成员存在,就允许临时 vector 存在?请参阅他的案例 2,其中创建了临时对象。
显然,此处使用了相同的构造,但我可能遗漏了一些东西。
编辑:根据下面 R. Martinho Fernandes 的回答,我尝试了以下操作:
int main()
{
using namespace std;
auto expr = math_vector<3>{1.0, 1.1, 1.2} + math_vector<3>{2.0, 2.1, 2.2};
cout << "vec1: "; for(int i = 0; i < 3; ++i) cout << expr.le()[i] << " "; cout << endl;
cout << "vec2: "; for(int i = 0; i < 3; ++i) cout << expr.re()[i] << " "; cout << endl;
}
事实证明,这是一个输出的有效代码:
vec1: 1.0 1.1 1.2
vec2: 2.0 2.1 2.2
因此,显然存储在表达式模板中的引用不是悬挂的。这是怎么回事?
最佳答案
what is different in Paul Preney' code in Expression templates and C++11 that permits the temporary vectors to exist as long as the rvalue-references members exist?
任何事情都不允许这样的事情发生。
那里的临时 vector 一直存在到完整表达式的末尾,就像任何其他未绑定(bind)到局部引用变量的临时 vector 一样。这在 Paul 的代码中就足够了,因为代码立即将表达式树具体化为实际的 math_vector
,之后就不再需要临时变量了。
Paul 的代码没有在任何地方存储任何表达式模板节点 (math_vector_expr
),而您的代码将一个 (X
) 存储为 x2
。这是 auto
的一个已知问题:当您使用表达式模板时,它会做错事,因为它会导致存储表达式树,这可能包含会立即变为悬空的引用。
为了说的清楚,下面这样就好了。
math_vector<3> result =
math_vector<3>{1.0, 1.1, 1.2} +
math_vector<3>{2.0, 2.1, 2.2} +
math_vector<3>{3.0, 3.1, 3.2} +
math_vector<3>{4.0, 4.1, 4.2}
; // no references are held to any temporaries past this point
下面的不行。
math_vector_expr<3> result = // or auto
math_vector<3>{1.0, 1.1, 1.2} +
math_vector<3>{2.0, 2.1, 2.2} +
math_vector<3>{3.0, 3.1, 3.2} +
math_vector<3>{4.0, 4.1, 4.2}
; // result now holds references to those temporaries
关于c++ - 数据成员和右值生命周期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18102501/
我正在开发一个使用多个 turtle 的滚动游戏。玩家 turtle 根据按键命令在 Y 轴上移动。当危害和好处在 X 轴上移动时,然后循环并改变 Y 轴位置。我尝试定义一个名为 colliding(
我不明白为什么他们不接受这个作为解决方案,他们说这是一个错误的答案:- #include int main(void) { int val=0; printf("Input:- \n
我正在使用基于表单的身份验证。 我有一个注销链接,如下所示: 以及对应的注销方法: public String logout() { FacesContext.getCurren
在 IIS7 应用程序池中有一个设置 Idle-time out 默认是 20 分钟,其中说: Amount of time(in minutes) a worker process will rem
我是一名优秀的程序员,十分优秀!