7

考虑以下代码:

#include <iostream>
#include <vector>
#include <array>

using namespace std;

typedef double (C_array)[10];

int main()
{ 
    std::vector<C_array> arr(10);

    // let's initialize it
    for (int i = 0; i < 10; i++)
        for (int j = 0; j < 10; j++)
            arr[i][j] = -1;

    // now make sure we did the right thing
    for (int i = 0; i < 10; i++)
    {
        for (int j = 0; j < 10; j++)
        {
            cout << arr[i][j] << " ";
        }
        cout << endl;
    }
}

我刚刚从@juanchopanza https://stackoverflow.com/a/25108679/3093378发现这段代码不应该是合法的,因为普通的旧式C数组是不可分配/可复制/可移动的。但是g++,即使使用-Wall -Wextra -pedantic. clang++不编译它。当然,如果我尝试做类似的事情auto arr1 = arr;,它会失败g++,因为它不知道如何复制arrarr1.

我在 OS X Mavericks 下使用g++4.9过。macports现场代码:http: //goo.gl/97koLa

我的问题是:

  1. 根据标准,此代码是否非法?
  2. g++这么牛逼吗?我一直在寻找很多简单的例子,其中g++盲目地编译非法代码,最后是昨天 用户定义的转换运算符优先级,在 g++ 但不是 clang++ 编译,并且没有太多努力,只是C++为了好玩而尝试。
4

1 回答 1

2

您的代码不是有效的 C++03。首先,头文件<array>不是 C++03 标准库的一部分,但这里也不需要它。二、vector对象的构造尝试调用构造函数

explicit vector(size_type n, const value_type& val = value_type(), const allocator_type& alloc = allocator_type());

但是,val 的初始化失败的原因与您无法编写的原因相同

C_array foo = C_array();

据我所知,C++03 标准第 5.2.3 节中的第 2 段仅允许此表示法用于非数组类型:

表达式 T(),其中 T 是非数组完整对象类型或(可能是 cv 限定的)void 类型的简单类型说明符 (7.1.5.2),创建指定类型的右值,即 value -initialized(8.5;没有对 void() 情况进行初始化)。

此外,g++-4.9.0 也拒绝编译代码,除非 -std=c++11 在命令行中提供:

foo.cpp: In constructor ‘std::vector<_Tp, _Alloc>::vector(std::vector<_Tp, _Alloc>::size_type, const value_type&, const allocator_type&) [with _Tp = double [10]; _Alloc = std::allocator<double [10]>; std::vector<_Tp, _Alloc>::size_type = long unsigned int; std::vector<_Tp, _Alloc>::value_type = double [10]; std::vector<_Tp, _Alloc>::allocator_type = std::allocator<double [10]>]’:
foo.cpp:11:32: error: functional cast to array type ‘std::vector<double [10]>::value_type {aka double [10]}’
 std::vector<C_array> arr(10);
...

至于 C++11,向量容器提供了一个额外的填充构造函数:

explicit vector (size_type n);

此构造函数要求模板类型是默认可构造的(参见第 23.3.6.2 节)。据我所知,这个要求在 C++11 中也没有满足(参见第 17.6.3.1 节),因为为了满足要求,表达式 C_array() 必须创建一个临时对象,这在 C+ 中也是无效的+11(再次参见第 5.2.3 节)。我不知道标准是否真的要求编译器拒绝代码,或者如果不满足其中一个要求但标准库的实现不需要它,是否允许编译器编译它。或许对C++11比较了解的人可以填补这里的空白。

除此之外,在我看来,尝试使用数组作为容器元素类型并不是一个好主意,因为其他容器要求没有得到满足。例如 C_array 不是可复制插入的,因此无法复制向量。

关于第二个问题:请随意浏览https://gcc.gnu.org/bugzilla/上的 gcc bugzilla 数据库。然而,接受无效代码也可以是故意的,例如为了不破坏遗留代码。

于 2014-08-20T16:53:37.493 回答