【问题标题】:C++ compiler warning(?) when passing uninitialized local variable to function将未初始化的局部变量传递给函数时的 C++ 编译器警告(?)
【发布时间】:2012-02-01 07:45:58
【问题描述】:

我对 C++ 很陌生,所以我希望有人能解释一下。我遇到了几个类似的话题,但我需要澄清一下。

因此,将已声明但未初始化的本地字符串传递给函数似乎是有效的。但是为什么当你用 int 或 float 尝试编译器时会报错呢??

无论是字符串、浮点数还是整数,内存地址在声明时都会被引用,即使它可能是“垃圾”

#include <iostream>
using namespace std;

void load(int);

int main()
{
    int salary;
    load(salary);
    return 0;
}

void load(int sal)
{
    cout << "your salary: " << endl;
    cin >> sal;
    cout << sal << endl;
}

如果我将 int 或 float 声明为全局变量,它会按预期工作而不会发出任何警告。 那么在全局空间中声明变量是更好的做法吗(我希望不是)?

所以把它放在全局中,它可以工作:

#include <iostream>
using namespace std;

int salary;
void load(int);

int main()
{
    load(salary);
    return 0;
}

void load(int sal)
{
    cout << "your salary: " << endl;
    cin >> sal;
    cout << sal << endl;
}

好的,另一个例子表明未初始化的全局变量在作为值传递给函数时起作用:(脱离大卫的评论)

int foo; 
int returnit(int j)
{ 
    cout << "your salary";
    cin >> j;
    return j; 
} 
int main() 
{ 
    int k = returnit(foo);
    cout << k; 
    return 0;
} 

无论如何,这里的教训是在传递给函数之前初始化原始数据类型。

【问题讨论】:

  • 那么你认为这段代码有什么作用?除了编译错误。
  • 是的,我知道它会编译错误。但是声明为全局变量而不进行初始化可以传递给函数。我试图理解为什么会这样。
  • 你错了,未初始化的全局变量也不能按值传递给函数。区别只是纯粹的运气——一种碰巧起作用,一种碰巧不起作用。
  • 为什么要将变量传递给该函数,而不是在函数中本地声明它?我的意思是它通过值传递,然后你在本地更改它并且永远不会返回任何东西。
  • 感谢您的所有 cmets。不要将未初始化的变量传递给函数,更重要的是为什么这样做没有用。

标签: c++ variables local initialization


【解决方案1】:

因此,将已声明但未初始化的本地字符串传递给函数似乎是有效的。但是为什么当你用 int 或 float 尝试编译器时会报错呢??

如果“字符串”是指std::string 对象,那是因为对象永远不会未初始化。当你这样做时:

std::string s;

然后调用std::string的默认构造函数,初始化对象。

原始数据类型的变量(例如intfloat),除非声明为具有静态 存储持续时间,否则如果未显式初始化,则会产生垃圾。尝试正确读取和使用该垃圾会触发警告。 (具有静态存储持续时间的原始数据类型的变量(即全局变量或声明为 static 的变量)被隐式初始化为 0。)

那么在全局空间中声明变量是更好的做法吗(我希望不是)?

不,更好的做法是初始化变量。

【讨论】:

  • ic,解释了为什么字符串可以工作,因为它不是原始数据类型并且已经初始化。
  • 你忘了说声明全局生命周期的变量在程序启动时默认初始化,这就是为什么它们也不会触发这些警告。
【解决方案2】:

解释为什么你不应该在函数调用中使用未初始化的变量的最好方法是因为这在逻辑上是无效的,有时在逻辑上是无效的,语法也是无效的。

要查看您的程序在逻辑上是否有效,请使用 box 方法并跟踪您的程序。全局盒子里面有全局变量, int main 有自己的盒子来保存它的局部变量,当函数被调用时,为该函数创建一个新盒子,并用它的参数和局部变量填充它。逐行更改变量值,因为它们在程序中发生变化。请记住仅使用常量作为全局变量。当你通过引用传递函数时要小心,你知道函数被赋予了内存中的变量地址并且可以更改该值。当使用传值时,在你的函数声明中使用这种语法:

int Multiplication(const int Var1, const int Var2);

这可以保护您传递给乘法的值。c++ 的语法是为速度而设计的,它不会阻止您在逻辑上不正确。

【讨论】:

  • 请使用段落。你的答案是一堵文字墙。
【解决方案3】:
int salary;
load(salary);

你认为你在这里传递给load的价值是什么?你传递了一个无意义的值。

要清楚,您传递的不是“未初始化变量”,而是传递未初始化变量的 。如果你这样做:

int j=3;
load(j);

您正在将j 的值(即3)传递给load。如果不另外指定,C++ 会按值传递。

全局变量也会有同样的问题:

int foo;

int returnit(int j)
{
    return j;
}

int main(void)
{
    int j=returnit(foo);

你认为j在这里应该有什么价值?!在将变量的值传递给函数之前,您仍然需要将其初始化为某个特定值。

【讨论】:

  • int foo; int returnit(int j){ cout > j;返回 j; } int main() { int j = returnit(foo); cout
  • 它可能在你的平台上工作,但它已经坏了。您将一个毫无意义的值传递给returnit。您可能会侥幸逃脱,因为returnit 忽略了该值。但是将值传递给函数只是让它忽略它有什么意义呢?
  • 我明白你的观点,大卫。但是,即使您在开始时可能不知道变量的值是什么,但在开始时声明变量不是一个好习惯吗?像这样 int foo; int returnit(int j){ cout > j;返回 j; } int main() { foo = returnit(foo); cout
  • 一切都很好除了foo的无意义值传递给returnit。只是不要那样做。它没有任何目的。这是非法的,无论如何函数都会忽略它。
  • @DavidSchwartz:实际上,对于全局变量,它确实可以移植。根据规范,全局变量在“实际”初始化之前初始化为零,这就是为什么在这种情况下没有错误。
【解决方案4】:

要补充大卫的答案,您可能想要做的(我猜)是修改原始薪水变量。为此,您需要传递对变量的引用,如下所示:

void load(int& sal)
{
    cout << "your salary: " << endl;
    cin >> sal;
    cout << sal << endl;
}

注意函数签名中 int 后面的“&”。

另请注意,您在 load() 中使用了未定义的“薪水”。您应该改用“sal”。

这样编译器就知道 load() 接收到一个变量的引用,所以如果你在函数内部修改它,你发送给函数的变量(salary)也会改变。

对函数的调用本身保持不变。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-06
    • 1970-01-01
    • 1970-01-01
    • 2012-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-12
    相关资源
    最近更新 更多