引用的统一初始化

18

我目前正试图理解C++0x的新统一初始化语法。不幸的是,我在使用统一初始化引用时遇到了困难。例如:

int main() {
   int a;
   int &ref{a};
}

这个示例运行良好:

% LANG=C g++ uniform_init_of_ref.cpp -std=c++0x -o uni -Wall -Wextra
uniform_init_of_ref.cpp: In function `int main()':
uniform_init_of_ref.cpp:3:10: warning: unused variable `ref' [-Wunused-variable]

(更新 Comeau对该示例抛出错误,所以也许gcc不应该编译它)

如果我使用自定义数据类型而不是整数,那么它就不能工作了:

class Y
{};

int main()
{
    Y y;
    Y &ref{y};
}

% LANG=C g++ initialization.cpp -std=c++0x -o initialization -Wall -Wextra
initialization.cpp: In function `int main()':
initialization.cpp:9:13: error: invalid initialization of non-const reference of type `Y&' from an rvalue of type `<brace-enclosed initializer list>'
initialization.cpp:9:8: warning: unused variable `ref' [-Wunused-variable]

很遗憾,我在标准草案中没有找到相关的部分。我的猜测是我对统一初始化的使用存在误解,因为Comeau显示了以下警告信息:

ComeauTest.c(9): error: reference variable "ref" requires an initializer
      Y &ref{y};

那么,你们中的某个人能指导我走向正确的方向吗?


如果你想知道为什么这个问题很重要,以及为什么我不只是使用Y &ref(y):我想能够在构造函数的初始化列表中使用统一初始化:

class X { };

class Y {
    const X& x;

    public:
        Y (const X& xx):
            x{xx}
        {}
};

int main () {
    X x;
    Y y{x};
}

这与上面的错误消息相同。

注意:

  • 我正在使用 LANG=C 来启用英文错误消息。
  • gcc 版本:4.6.1

gcc 4.4.1也无法编译第一个示例:uniform_init_of_ref.cpp:3: error: ISO C++ forbids use of initializer list to initialize reference 'ref' - rmflow
2
@rmflow:gcc4.4并没有完全实现统一初始化。 - R. Martinho Fernandes
据我所见,您可以在构造函数初始化列表中使用普通的x(xx),我认为没有必要使用新颖的统一格式:-) - Cheers and hth. - Alf
1
@alf-p-steinbach 是的,但我想避免在构造函数中使用相同的初始化样式,而不根据需要初始化的内容更改样式。 - evnu
2
@evnu:实际上,我认为抱怨是正确的,因为如果我正确地阅读了N2672,对于非const对象的左值引用,无论它们是原始类型还是类类型,都不应该允许以这种方式初始化。 - Jan Hudec
显示剩余2条评论
1个回答

6
根据N2672,第8.5.4.4段应该这样说:
否则,如果T是引用类型,则会初始化一个rvalue临时变量,其类型为T所引用的类型,并将该引用绑定到该临时变量。[注意:与往常一样,如果引用类型是非const类型的左值引用,则绑定将失败,程序将不合法。]
这意味着引用的统一初始化将它们绑定到新的匿名实例,因此我认为它是相当无用的。这仍然不能解释为什么一个可行而另一个不可行;它们应该表现相同(除非Y有一些显式构造函数)。

因此,在第一个示例中,执行ref = 42不会修改a - Alexandre C.
@alexandre-c 在第一个例子中将值分配给ref会改变这里的a的值。 - evnu
@evnu:这种行为与@Jan引用的不符合。你有和Comeau核对过吗? - Alexandre C.
@alexandre-c Comeau在第一个示例中抛出错误。我会更新我的答案。 - evnu
1
这几乎就是n3290所说的,只不过它使用prvalue临时对象而不是rvalue临时对象 - Ben Voigt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接