相关疑难解决方法(0)

C#在foreach中重用变量是否有原因?

在C#中使用lambda表达式或匿名方法时,我们必须警惕对修改后的闭包陷阱的访问.例如:

foreach (var s in strings)
{
   query = query.Where(i => i.Prop == s); // access to modified closure
   ...
}
Run Code Online (Sandbox Code Playgroud)

由于修改后的闭包,上面的代码将导致Where查询中的所有子句都基于最终值s.

正如这里所解释的那样,这是因为上面循环中s声明的变量foreach在编译器中被翻译成这样:

string s;
while (enumerator.MoveNext())
{
   s = enumerator.Current;
   ...
}
Run Code Online (Sandbox Code Playgroud)

而不是像这样:

while (enumerator.MoveNext())
{
   string s;
   s = enumerator.Current;
   ...
}
Run Code Online (Sandbox Code Playgroud)

正如这里所指出的,循环外声明变量没有性能优势,在正常情况下,我能想到这样做的唯一原因是你计划在循环范围之外使用变量:

string s;
while (enumerator.MoveNext())
{
   s = enumerator.Current;
   ...
}
var finalString = s;
Run Code Online (Sandbox Code Playgroud)

但是,foreach循环中定义的变量不能在循环外使用: …

c# foreach lambda scope anonymous-methods

1631
推荐指数
4
解决办法
10万
查看次数

闭包中变量捕获的详细说明

我已经看到关于变量捕获如何为变量创建闭包的无数帖子,但是它们似乎都没有具体细节,并且把整个事情称为"编译魔术".

我正在寻找一个明确的解释:

  1. 如何实际捕获局部变量.
  2. 捕获值类型与引用类型之间的差异(如果有).
  3. 并且是否存在关于值类型的任何装箱.

我倾向于根据值和指针(更接近内部发生的核心)的答案,尽管我会接受一个涉及值和引用的明确答案.

.net c# closures value-type reference-type

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

基于范围的临时对象

我知道一般来说,基于范围的for循环中临时的生命周期延伸到整个循环(我读过C++ 11:基于范围的语句:"range-init"生命周期?).所以做这样的事情一般都可以:

for (auto &thingy : func_that_returns_eg_a_vector())
  std::cout << thingy;
Run Code Online (Sandbox Code Playgroud)

现在,当我尝试做一些我认为与Qt QList容器类似的事情时,我对内存问题感到磕磕绊:

#include <iostream>
#include <QList>

int main() {
  for (auto i : QList<int>{} << 1 << 2 << 3)
    std::cout << i << std::endl;
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

这里的问题是valgrind在QList类中的某个地方显示无效的内存访问.但是,修改示例以便将列表存储在变量中可以提供正确的结果:

#include <iostream>
#include <QList>

int main() {
  auto things = QList<int>{} << 1 << 2 << 3;
  for (auto i : things)
    std::cout << i << std::endl;
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

现在我的问题是:我在第一种情况下做了一些愚蠢的事情,导致例如未定义的行为(我没有足够的经验阅读C++标准以便为自己回答这个问题)?或者这是我如何使用QList或如何QList …

c++ qt c++11

18
推荐指数
2
解决办法
2451
查看次数