全局const字符串并且闻起来对我不好,它真的安全吗?

Jam*_*are 11 c++ string anonymous const object

我正在审查一个同事的代码,我发现他在全球范围内定义了几个常量:

const string& SomeConstant = "This is some constant text";
Run Code Online (Sandbox Code Playgroud)

就个人而言,这对我来说闻起来很糟糕,因为引用是指我假设的是一个从给定的char数组构造的"匿名"对象.

从语法上讲,它是合法的(至少在VC++ 7中),它似乎运行,但实际上我宁愿让他删除&因此对它正在做什么没有歧义.

那么,这真的很安全合法吗?我很着迷吗?构造的临时对象是否具有保证的寿命?我一直认为以这种方式使用的匿名对象在使用后被破坏了......


所以我的问题也可以推广到匿名对象的生命周期.标准是否规定了匿名对象的生命周期?它是否与同一范围内的任何其他对象具有相同的生命周期?或者只给出表达式的生命周期?


此外,当它作为本地时,它显然有不同的范围:

class A
{
    string _str;

public:
    A(const string& str) :
        _str(str)
    {
        cout << "Constructing A(" << _str << ")" << endl;
    }

    ~A()
    {
        cout << "Destructing A(" << _str << ")" << endl;
    }
};

void TestFun()
{
    A("Outer");
    cout << "Hi" << endl;
}
Run Code Online (Sandbox Code Playgroud)

显示:

构建A(外部); 破坏A(外); 你好

Mat*_*hen 14

这完全合法.在程序结束之前不会被破坏.

编辑:是的,保证:

"所有没有动态存储持续时间,没有线程存储持续时间且不是本地的对象都有静态存储持续时间.这些对象的存储应持续到程序的持续时间(3.6.2,3.6.3). "

- 2008年工作草案,编程语言C++标准,§3.7.1p.63

正如马丁所说,这不是完整的答案.标准草案进一步注释(第12.2节,第250-1页):

"类型的临时类型是在各种上下文中创建的:将rvalue绑定到引用(8.5.3)[...]即使避免创建临时对象(12.8),也应该尊重所有语义限制,就好像临时对象已被创建.[...]临时对象被作为评估全表达式(1.9)的最后一步被销毁,该表达式(词法上)包含创建它们的点.[...]有两种情况其中temporaries在不同于完整表达式结束时销毁的时间.[...]第二个上下文是当引用绑定到临时时.引用绑定的临时值或临时值是临时值除了下面指定的内容之外,参考所绑定的子对象的完整对象在参考的生命周期内仍然存在."

我用g ++测试过,如果这让你感觉更好.;)

  • 标准的部分不适用.在分配的RHS上创建的临时值具有静态存储持续时间.表达式完成后通常会被销毁.它不被破坏的唯一原因是它被一个const&绑定,从而延长了它的寿命. (4认同)
  • 作为旁注:通过调用临时的原始析构函数而不是有界引用的析构函数来销毁由引用绑定的临时对象.换句话说:如果将Derived绑定到Base&,则临时的生命周期将延长到Base的生命周期,并且当引用超出范围时〜将调用Derived(无论Base是否具有虚拟析构函数)所以你可以在没有vtable的情况下获得'virtual destructor'语义 (2认同)

Mar*_*ork 11

是的,这是有效和合法的.

const string& SomeConstant = "This is some constant text";

// Is equivalent too:

const string& SomeConstant = std::string("This is some constant text");
Run Code Online (Sandbox Code Playgroud)

因此,您正在创建一个临时对象.
此临时对象绑定到const&,因此其生命周期延长到它绑定的变量的生命周期(即,比创建它的表达式更长).

这是标准保证.

注意:

虽然这是合法的.我不会用它.最简单的解决方案是将其转换为const std :: string.

用法:

在这种情况下,因为变量在全局范围内,所以它对程序的全长有效.因此,只要执行进入main(),就可以使用它,并且在执行退出main()之后不应该访问它.

虽然在此之前技术上可能是可用的,但是在全局对象的构造函数/析构函数中对它的使用应该通过已知的全局变量初始化顺序问题进行调整.

额外的想法:

另一方面,这不会遇到问题:

char const* SomeConstant = "This is some constant text";
Run Code Online (Sandbox Code Playgroud)

并且可以在任何时候使用.只是一个想法.


ral*_*nja 6

这可能是合法的,但仍然很难看.省略参考!

const string SomeConstant = "This is some constant text";
Run Code Online (Sandbox Code Playgroud)

  • 这就是我所倾向的,因为在这种情况下,并没有给你买任何东西.但如果它合法且正式如此,我不愿意为此敲门. (2认同)