【问题标题】:C++ initialization of automatics and scope自动和范围的 C++ 初始化
【发布时间】:2012-04-04 08:59:29
【问题描述】:

谁能指出我在 C++ 标准中的一个参考,它保证我在函数 foo1() 中的自动 char* q将始终在 foo1() 中调用 p = bar() 后初始化。我非常习惯于在 foo2() 中创建一个新块,并且想知道我是否对优化编译器过于块状和偏执。或者我的偏执是正确的,不应该假设编译器不会优化代码,使得 p = bar() 总是在 q(p) 之前被调用? 谢谢!

#include <stdio.h>
#include <stdlib.h>
#include <strings.h>


char* bar()
{
    char* t = (char*)malloc(15);
    strcpy(t, "Hello World!");
    return t;
}

void foo1(void)
{
    char* p = NULL;

    printf("foo1: do some stuff\n");

    p = bar();

    printf("foo1: do some more stuff\n");

    char* q(p);

    printf("foo1: q says:%s\n", q);

    free(p);
}

void foo2(void)
{
    char* p = NULL;

    printf("foo2: do some stuff\n");

    p = bar();

    printf("foo2: do some more stuff\n");

    // is this block necessary?
    {
        char* q(p);

        printf("foo2: q says:%s\n", q);
    }

    free(p);
}

int main(int ac, char* av[])
{
    foo1();
    foo2();
    return 0;
}

【问题讨论】:

  • 哇——你能说“冒充 C++ 的可怕 C 代码”吗?
  • 目前我无法指出标准的特定部分,但要查找的关键短语是 sequence point
  • @Steve 我更喜欢将char* q = p; 写成char* q(p);,这样就不会与q 混淆了,这是一个接受p 类型参数并返回char* 的函数.
  • @Steve:为了人类,请使用std::string。没有理由像现在这样一直在 C++ 中通过 malloc()/free() 手动管理内存。 tinyurl.com/dont-use-pointers
  • @DeadMG、Mahesh 和 tiny:对于使用“C”代码作为 C++ 来呈现问题,我深表歉意。有些'C'编译器会编译这个,有些不会。到目前为止,我尝试过的所有 C++ 编译器都会。我想不出一种更简单的方法来用更少的 LOC 来传达问题。感谢您的主题回复。

标签: c++ initialization scope


【解决方案1】:

由于sequence points 的存在,您可以放心地假设p = bar() 将出现在char * q(p) 之前。

我现在不能让自己涉足 C++ 标准,但我可以为您提供 C99 标准的等价物,希望能让您放心:

5.1.2.3:

访问 volatile 对象、修改对象、修改文件或调用函数 执行这些操作中的任何一个都是副作用,它们是状态的变化 执行环境。表达式的评估可能会产生副作用。在 执行序列中的某些指定点称为序列点,所有副作用 之前的评估应该是完整的,并且没有后续评估的副作用 应该已经发生了。

附件 C: (强调我的)

以下是5.1.2.3中描述的顺序点:

  • 来电 在对参数进行评估之后,传递给函数。
  • 以下运算符的第一个操作数的结尾:逻辑与 &amp;&amp;;逻辑或||;有条件的?;逗号,
  • 完整声明符的结尾;
  • 该 完整表达式的结尾:初始化器; an中的表达式 表达语句; a 的控制表达式 选择声明(ifswitch);控制表达式 whiledo 声明的; for 的每个表达式 陈述; return 语句中的表达式。
  • 就在库函数返回之前。
  • 之后 与每个格式化输入/输出函数相关的动作 转换说明符。
  • 紧接在之前和 每次调用比较函数之后,以及 对比较函数的任何调用和对象的任何移动 作为参数传递给该调用。

【讨论】:

  • 我认为 C++11 丢弃了“sequenced before”和“sequenced after”的序列点。
  • @bames53 :确实如此,但只是措辞发生了变化——语义旨在保持与 C++03 相同,只是措辞更清晰。
【解决方案2】:

您不必如此偏执。 C++ 说

与 全表达式在每个值计算和边之前排序 与要评估的下一个完整表达式相关联的效果。

[intro.execution] 1.9 /14 ,n3337

【讨论】:

  • +1 以获得正确答案。但你为什么要引用 N3337。我的意思是,N3290 与当前标准(C++11)相同,而 N3337 是下一个标准的初稿?
  • @Cheersandhth.-Alf : N3290 已经有一段时间没有免费提供了;也许bames根本没有副本?
  • @Cheersandhth.-Alf n3337 是 C++11 后标准的第一个草案。它包含已发布的 C++11 标准的所有内容,但修正了一些拼写错误等。
【解决方案3】:

C++03 6.7/2“声明声明”说:

每次执行声明语句时都会初始化具有自动存储持续时间 (3.7.2) 的变量。在块中声明的具有自动存储持续时间的变量在退出块时被销毁

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-08-14
    • 2017-07-21
    • 2013-07-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-08
    • 1970-01-01
    相关资源
    最近更新 更多