当{}与new一起使用以创建std :: array

问题描述 投票:1回答:1
时,将绕过T的默认构造函数

让我们考虑这堂课:

class A {
public:
    A() = delete;

    A(int i) :
            i_m(i) {
        std::cout << __PRETTY_FUNCTION__ << ' ' << i_m << '\n';
    }

    ~A() {
        std::cout << __PRETTY_FUNCTION__ << ' ' << i_m << '\n';
    }

private:
    int i_m{1234567890};
};

默认构造函数被明确删除,因此AFAIK A只能由整数构造。永远不会使用数据成员i_m的默认初始化。

让我们考虑这个程序:

int main() {
    using T = std::array<A, 2>;

    //T a;
    // error: use of deleted function 'std::array<A, 2>::array()'
    // note: 'std::array<A, 2>::array()' is implicitly deleted because the default definition would be ill-formed
    // error: use of deleted function 'A::A()'

    //T b{};
    // error: use of deleted function 'A::A()'
}

再次,对我来说,这似乎完全没问题。

现在让我们考虑其他程序:

int main() {
    using T = std::array<A, 2>;
    auto foo = new T{};
    delete foo;

    auto foo_init = new T{1, 2};
    delete foo_init;

//  auto zorg = new T();
//  delete zorg;
//  error: use of deleted function 'std::array<A, 2>::array()'
//  note: 'std::array<A, 2>::array()' is implicitly deleted because the default definition would be ill-formed:
//  error: use of deleted function 'A::A()'

    auto zorg_init = new T({3, 4});
    delete zorg_init;
}

此代码确实编译(无警告)并生成以下输出:

A::~A() 0
A::~A() 38870160
A::A(int) 1
A::A(int) 2
A::~A() 2
A::~A() 1
A::A(int) 3
A::A(int) 4
A::~A() 4
A::~A() 3

现在对我来说似乎有些[[不是很好”。怎么可能auto foo = new T{};行不被认为格式错误?这里完全绕过了类A的初始化。

此代码不编译毫无价值:

int main() { auto p = new A{}; delete p; }

错误是预期的:

error: use of deleted function 'A::A()'

我使用以下选项测试了这些代码:-Wall -Wextra -pedantic -std=c++17gcc -v给出:gcc version 7.2.0 (x86_64-posix-sjlj-rev0, Built by MinGW-W64 project)在我的计算机上。

任何解释将不胜感激:)


PS:在Compiler Explorer中进行详尽测试(与示例https://godbolt.org/z/5VZLU_结合使用)之后,看来这是gcc 7.x中的问题。实际上,只有gcc的7.x版本可以编译此示例。 gcc 6.4并非没有。 gcc 8.1都不是。既不。 msvc都没有。

您可以确认此处没有UB,这确实是编译器错误吗?

c++ arrays constructor compiler-errors new-operator
1个回答
0
投票
这确实是GCC编译器错误。

如果您看以下使用空括号对而不是初始化列表的代码:

int main() { using T = std::array<A, 2>; auto foo = new T(); // here delete foo; return 0; }

它将抛出错误:

错误:使用删除的功能'std :: array :: array()'

auto foo = new T();

与使用初始化程序列表并使用不同于7.x的编译器版本进行编译时出现的错误相同。
© www.soinside.com 2019 - 2024. All rights reserved.