为什么这个 C++ 有效? (declaration/definition 个变量)
Why is this C++ working? (declaration/definition of variables)
为什么我可以在 for 循环的每次迭代中声明和定义 3 个变量 [for (auto vall: k0L){...}]?当我执行 g++ code.cpp 时,编译器不会抱怨。
我知道一个变量只能声明一次。
我知道我不能写 int a = 5;整数 = 6;在 main() 范围内。
但是,这就是我在那个 for 循环中所做的。
谢谢!
#include <iostream>
#include <vector>
#include <fstream>
#include <math.h>
#include <algorithm>
#define PI 3.14159265
std::vector<double> linspace (double start, double end, size_t points) { // will be used in main(), details of this function are not important.
std::vector<double> res(points);
double step = (end - start) / (points - 1);
size_t i = 0;
for (auto& e: res) {
e = start + step * i++;
}
return res;
}
int main() {
std::vector<double> k0L = linspace (0,20, 10000); // a linearly spaced vector with 10000 values between 0,20
std::vector<double> f_ra;
**// QUESTION : Why can I declare and define tau, phi_of_tau, to_push_back, at each iteration of the following for-loop?**
for (auto vall: k0L) {
double tau = pow(vall, (1./3.)) * sin(20.0*PI/180.0); // something1
double phi_of_tau = 2.1 * tau * exp(- (2./3.) * pow(tau,3) ); // something2
double to_push_back = 0.5 * pow(phi_of_tau, 2); // something_total, composed of something1 and something2
f_ra.push_back(to_push_back); // equivalent to instruction below
// f_ra.push_back(0.5 * pow(2.1 * (pow(vall, (1./3.)) * sin(30.0*PI/180.0)) * exp(- (2./3.) * pow((pow(vall, (1./3.)) * sin(20.0*PI/180.0)),3)), 2));
}
// Write values to a file
std::ofstream myfile("fra_vs_k0L_30degrees.dat");
for (auto i=0; i<= f_ra.size(); i++) {
myfile << k0L[i] << " " << f_ra[i] << std::endl;
}
return 0;
} // END main()
这是由于范围。所有这些变量仅在 for 循环中可用。
如果你有这个代码
if(true) {
int a = 1;
}
// notice a is not defined here, only in the if
if(true) {
int a = 2;
}
它也不会抱怨
因为 C++ 中的作用域就是这样工作的:这些变量的作用域是 for
循环的主体 。换句话说:它们是在每个循环迭代中创建的,并且一直存在到同一迭代结束。
这完全等同于即使多次调用函数也可以在函数内声明局部变量:
int f(int x) {
int a = x * 2;
return a;
}
int main() {
f(2);
f(2);
}
当然这不会让你感到惊讶,你不认为 f
里面的 a
被重新定义了吗?
虽然与 for 循环语法相关的其他答案是正确的,但我认为 OP 询问的是 C++11 基于范围的 for 循环语法,这让 him/her 担心。
此 for (auto a : container) {...}
是 C++11 的基于范围的 for 循环语法,用于在每个步骤上使用引用 a
迭代 container
数据结构,关键字 auto
表示 a
的类型将是 container
对象的类型。
可以在此处找到更多详细信息:https://en.cppreference.com/w/cpp/language/range-for
C++ 允许您在循环中使用 declare/define 个变量。变量的内存在循环开始时分配一次,因为这些变量是在循环内声明的,所以它们的范围仅限于该循环内。
这可能是一种很好的做法,因为限制变量的范围通常是正确的做法,并且可以更轻松地进行调试。应该注意的是,变量不应在循环之间保留它们的值,并且在您的特定示例中,它们的值每次都会重新初始化。由于您有一些相当复杂的数学运算来初始化这些变量,这可能会对性能造成有意义的消耗,因为这些计算是为了在每个循环中初始化变量而完成的。由于看起来这些变量保持常量值,因此在您的情况下,最好在循环范围之外定义变量,这样计算只完成一次。希望对您有所帮助!
以下页面也很好地解决了这个问题:)
Declaring variables inside loops, good practice or bad practice?
为什么我可以在 for 循环的每次迭代中声明和定义 3 个变量 [for (auto vall: k0L){...}]?当我执行 g++ code.cpp 时,编译器不会抱怨。 我知道一个变量只能声明一次。 我知道我不能写 int a = 5;整数 = 6;在 main() 范围内。 但是,这就是我在那个 for 循环中所做的。 谢谢!
#include <iostream>
#include <vector>
#include <fstream>
#include <math.h>
#include <algorithm>
#define PI 3.14159265
std::vector<double> linspace (double start, double end, size_t points) { // will be used in main(), details of this function are not important.
std::vector<double> res(points);
double step = (end - start) / (points - 1);
size_t i = 0;
for (auto& e: res) {
e = start + step * i++;
}
return res;
}
int main() {
std::vector<double> k0L = linspace (0,20, 10000); // a linearly spaced vector with 10000 values between 0,20
std::vector<double> f_ra;
**// QUESTION : Why can I declare and define tau, phi_of_tau, to_push_back, at each iteration of the following for-loop?**
for (auto vall: k0L) {
double tau = pow(vall, (1./3.)) * sin(20.0*PI/180.0); // something1
double phi_of_tau = 2.1 * tau * exp(- (2./3.) * pow(tau,3) ); // something2
double to_push_back = 0.5 * pow(phi_of_tau, 2); // something_total, composed of something1 and something2
f_ra.push_back(to_push_back); // equivalent to instruction below
// f_ra.push_back(0.5 * pow(2.1 * (pow(vall, (1./3.)) * sin(30.0*PI/180.0)) * exp(- (2./3.) * pow((pow(vall, (1./3.)) * sin(20.0*PI/180.0)),3)), 2));
}
// Write values to a file
std::ofstream myfile("fra_vs_k0L_30degrees.dat");
for (auto i=0; i<= f_ra.size(); i++) {
myfile << k0L[i] << " " << f_ra[i] << std::endl;
}
return 0;
} // END main()
这是由于范围。所有这些变量仅在 for 循环中可用。 如果你有这个代码
if(true) {
int a = 1;
}
// notice a is not defined here, only in the if
if(true) {
int a = 2;
}
它也不会抱怨
因为 C++ 中的作用域就是这样工作的:这些变量的作用域是 for
循环的主体 。换句话说:它们是在每个循环迭代中创建的,并且一直存在到同一迭代结束。
这完全等同于即使多次调用函数也可以在函数内声明局部变量:
int f(int x) {
int a = x * 2;
return a;
}
int main() {
f(2);
f(2);
}
当然这不会让你感到惊讶,你不认为 f
里面的 a
被重新定义了吗?
虽然与 for 循环语法相关的其他答案是正确的,但我认为 OP 询问的是 C++11 基于范围的 for 循环语法,这让 him/her 担心。
此 for (auto a : container) {...}
是 C++11 的基于范围的 for 循环语法,用于在每个步骤上使用引用 a
迭代 container
数据结构,关键字 auto
表示 a
的类型将是 container
对象的类型。
可以在此处找到更多详细信息:https://en.cppreference.com/w/cpp/language/range-for
C++ 允许您在循环中使用 declare/define 个变量。变量的内存在循环开始时分配一次,因为这些变量是在循环内声明的,所以它们的范围仅限于该循环内。
这可能是一种很好的做法,因为限制变量的范围通常是正确的做法,并且可以更轻松地进行调试。应该注意的是,变量不应在循环之间保留它们的值,并且在您的特定示例中,它们的值每次都会重新初始化。由于您有一些相当复杂的数学运算来初始化这些变量,这可能会对性能造成有意义的消耗,因为这些计算是为了在每个循环中初始化变量而完成的。由于看起来这些变量保持常量值,因此在您的情况下,最好在循环范围之外定义变量,这样计算只完成一次。希望对您有所帮助!
以下页面也很好地解决了这个问题:)
Declaring variables inside loops, good practice or bad practice?