在 C++17 中分配给数组
Assignment to array in C++17
下面是一些代码:
int main()
{
using T = int[3];
T a;
a = T{};
}
据我所知,根据 C++17 标准,这段代码是正确的,但是我尝试的每个编译器都拒绝了它。
这段代码真的不正确吗?如果是,根据标准的哪些条款?
到目前为止,我的调查:在 C 和旧版本的 C++ 中,代码不正确,因为赋值运算符的左操作数必须是可修改的左操作数,a
要么不是,要么指定不清楚。但是由于C++17a
被明确指定为可修改的左值(C++17 [basic.lval]/7)。
数组到指针的转换在这里不应用:[expr.ass] 没有明确指定它,[expr]/9 和 [expr]/10 似乎不适用:=
期望 prvalue 作为右操作数,并且提供了一个 prvalue。(它期望一个 glvalue 作为左操作数,并且提供了一个 glvalue)。这些条款适用于在预期价值的地方提供了glvalue的情况,反之亦然。
[expr.ass]/3 表示右表达式隐式转换为左操作数的类型。但由于双方具有相同的类型int[3]
因此似乎没有必要进行转换。
因此,我没有看到任何条款可以排除 [expr.ass]/2 的应用,即右侧的值存储在左侧引用的对象中。
最新的草案围绕[basic.lval]/7和[expr]/9-10中的条款移动,但似乎没有改变它们的含义,它甚至重新措辞[expr.ass]/2以更清楚:
在简单赋值(
=
)中,左操作数所指的对象被修改为右操作数的结果,将其值替换为右操作数的结果。
据我所知,"可修改的左值"的定义要么在C++中指定不足,要么故意将数组指定为可分配(我怀疑前者是正确的,因为没有编译器做后者)。
该标准(最新草案)说:
[基本.lval]
左值是可修改的,除非其类型是常量限定的或函数类型。
这非常简洁,但没有排除数组。
此外,至少自 C++03 年以来,标准版本没有改变这一点,其中指定以下内容:
[基本.lval]
11 函数不能修改,但指向函数的指针是可以修改的。
12 指向不完整类型的指针是可以修改的。
13 常量限定表达式的指称不得修改......
这基本上是相同的,除了使用更多的描述性而不是确定性的措辞。不排除数组。
相比之下,C11标准非常明确(引用N1548草案):
6.3.2.1 左值、数组和函数指示符
1 ...可修改的左值是没有数组类型的左值,...
因为内置运算符也受 [over.built] 控制,即:
表示子句 [expr] 中定义的内置运算符的候选运算符函数在此子句中指定。
对于赋值运算符,相应函数的形式为:
over.built#19
对于每个三元组(L,vq,R),其中L是算术类型,R是提升的算术类型,存在以下形式的候选算子函数
对于每对 (T, vq),其中 T 是任何类型,存在以下形式的候选运算符函数:
T vq&operator=(T vq&, T*);
对于每个对 (T, vq),其中 T 是枚举或指向成员类型的指针,存在以下形式的候选运算符函数
vq T& operator=(vq T&, T);
因此,当a, T{}
相应的参数时,它们都不能作为候选函数。 因此,程序应该是格式错误的。
C++ 标准中没有关于 prvalue 数组具体化的规定,正如您在 [class.temporary]/5 的注释 3 中看到的那样,它总结了这些具体化发生的情况。
- 在c++中为我自己的基于指针的数组分配内存的正确方法
- 具有自定义构造函数 (C++) 的类型的动态数组分配
- 如何通过 malloc 为队列数组分配内存?
- 具有动态数组分配的OpenMP嵌套循环
- 如何为数组结构的数组分配内存
- 如何为结构数组分配内存?
- cpp 数组 - 分配常量索引有效,而非常量索引不起作用
- 如何为字符指针数组分配内存?
- 在 C++ 中初始化后的数组分配
- 将数据分配给了数组分配,但程序显示了以缓冲区超支的输出
- C++函数问题中的数组分配
- 子数组分配:使用聚合对象错误的预期"{...}"进行初始化
- 为什么我的指针数组分配不起作用
- std::堆栈和堆栈溢出错误的数组分配
- 在 c++ 中是否有通过声明"implicit"数组分配?
- 在 c++ 中为 2-D "Dynamically Created"数组分配值时遇到问题
- 如何为C++数组分配指向第一个元素的指针
- 字符数组分配
- 将数组分配在固定数量的线程之间
- 为构造函数中的数组分配值