const引用的文字初始化

时间:2010-01-18 18:29:01

标签: c++ reference variables initialization

以下代码如何在C ++中运行?这是合乎逻辑的吗?

const int &ref = 9;
const int &another_ref = ref + 6;

为什么C ++允许对const引用进行文字初始化,而非const引用不允许这样做? E.g:

const int days_of_week = 7;
int &dof = days_of_week; //error: non const reference to a const object

这可以通过以下事实来解释:非const引用可用于更改它所引用的变量的值。因此,C ++不允许对const变量进行非const引用。

这可能是一个可能的解释吗? C ++不允许:

int &ref = 7;

因为这不符合逻辑,但是:

const int &ref = 7;

几乎相当于:

const int val = 7;

因此const变量允许进行文字初始化。

P.S。:我目前正在研究Lippman的C ++入门。

3 个答案:

答案 0 :(得分:11)

可以使用文字和临时值初始化常量引用,因为您可以将它们简单地转换为显式变量:

int const& ans = 42;
// tranformed:
int __internal_unique_name = 42;
int const& ans = __internal_unique_name;

或者延长寿命时,例如函数参数:

f("foobar");
// transformed:
{
  string __internal_unique_name = "foobar";
  f(__internal_unique_name);
}

(注意这种情况下的显式块。)

虽然在非常数情况下可以做类似的事情,但在当前的C ++中是不允许的。但是,C ++ 0x(下一个标准)将具有r值引用。


如果不清楚,代码中的ref + 6会创建一个临时对象,您可以将其视为:

int const& ref = int(9);
int const& another_ref = int(ref + 6);

// transformed:
int __A = 9;
int const& ref = __A;
int __B = ref + 6;
int const& another_ref = __B;

这可以帮助您理解/可视化正在发生的事情,但您不应该编写这样的真实代码。此外,我使用双下划线名称来说明这些名称是实现细节(由编译器使用),不应该被您使用。包含相邻下划线的任何名称都保留给C ++实现。

答案 1 :(得分:9)

所以你可以写这样的代码:

void f( const string & s ) {
}

f( "foobar" );

虽然严格来说这里实际发生的事情并不是文字绑定到const引用 - 而是创建了一个temprary字符串对象:

string( "foobar" );

并且此无名字符串绑定到引用。

请注意,创建非参数引用变量实际上是非常不寻常的 - 引用的主要目的是作为函数参数和返回值。

答案 2 :(得分:2)

您的代码归结为C ++标准规则,其中临时值的生命周期绑定到分配给它的const引用的生命周期。有关其他详细信息,请参阅GoTW文章GotW #88: A Candidate For the “Most Important const”

例如,Alexandrescu和Marginean在Dr. Dobbs文章“Generic: Change the Way You Write Exception-Safe Code — Forever”中描述的ScopeGuard实现取决于此行为。