【问题标题】:scopes and c++ pointers作用域和 C++ 指针
【发布时间】:2012-01-09 15:48:30
【问题描述】:

我有以下代码:

using namespace std;
vector<string*> v;
{
  string s = "hello";
  v.push_back(&s);
}
{
  string ss = "goodbye";
  v.push_back(&ss);
}

cout << v.at(0)->c_str() << endl;
cout << v.at(1)->c_str() << endl;

打印出来的

goodbye
goodbye

如果我删除范围括号,代码将打印出来

hello
goodbye

当我离开第一个作用域时究竟发生了什么,指向第一个字符串的指针现在指向第二个?

【问题讨论】:

标签: c++ scope


【解决方案1】:

存储的指针在作用域之后变成悬空指针,任何读取它们指向的内容的尝试都会产生未定义的行为。

【讨论】:

  • 那是我认为应该发生的事情,但我不得不问结果是不变的事实。
  • 未定义的行为意味着任何事情都可能发生,包括获得正常外观、一致的结果。这是未定义行为如此糟糕的原因之一;在编写程序时你甚至可能没有注意到它,但在某些其他情况下你的程序可能会发生灾难性的失败。
  • @Bg1987:未定义的行为并不意味着随机行为。真正的随机性并不真正存在 :) 这意味着将发生的事情不受任何规则的约束(从标准的角度来看),但编译器的输出仍然受编译器的代码生产规则的约束,所以范围它可以提供的行为是有限的。
  • @MatthieuM。但不是很。未定义行为的最常见表现是代码与您的所有测试完美配合,但在最重要的客户面前的演示中却失败了。或者当您在代码中完全不同的位置插入完全不相关的行时。或者当您更改编译器选项,或为编译器修复错误时。
【解决方案2】:

出现未定义的行为会发生什么情况,因为 s 在您调用 cout&lt;&lt; 运算符时已超出范围。

它不会崩溃,因为 sss 恰好与您的特定架构和 C++ 的实现具有相同的地址。换句话说,尝试在其他架构或其他编译器上复制您的实验的其他人可能会得到不同的结果。

【讨论】:

    【解决方案3】:

    实际上,系统正在重用它用于字符串 s 的内存来保存字符串 ss。但这恰好是编译器管理内存的方式。根据 C++ 标准,您不能依赖任何此类行为,并且您发布的代码的实际结果是未定义的。

    【讨论】:

      【解决方案4】:

      您正在取消引用两个指向已销毁的两个对象的指针:这是未定义的行为。 在这里什么都可能发生。

      【讨论】:

      • 让指针指向某个无效位置并不是未定义的行为;取消引用它们是
      猜你喜欢
      • 2011-06-01
      • 2020-12-09
      • 2015-02-13
      • 1970-01-01
      • 1970-01-01
      • 2017-06-14
      • 2020-08-19
      • 2021-08-14
      • 1970-01-01
      相关资源
      最近更新 更多