C++ 使用私有复制/移动构造函数聚合初始化
我在测试一些初始化聚合的东西时遇到了这个问题。我使用的是GCC4.6 当我用列表初始化聚合时,所有成员都在原地构造,没有复制或移动。也就是说:C++ 使用私有复制/移动构造函数聚合初始化,c++,gcc,c++11,initialization,C++,Gcc,C++11,Initialization,我在测试一些初始化聚合的东西时遇到了这个问题。我使用的是GCC4.6 当我用列表初始化聚合时,所有成员都在原地构造,没有复制或移动。也就是说: int main() { std::array<std::array<Goo,2>,2> a { std::array<Goo,2>{Goo{ 1, 2}, Goo{ 3, 4}} , std::array<Goo,2>{Goo{-1,-2}, Goo{-3,-4}} }; }
int main()
{
std::array<std::array<Goo,2>,2>
a { std::array<Goo,2>{Goo{ 1, 2}, Goo{ 3, 4}} ,
std::array<Goo,2>{Goo{-1,-2}, Goo{-3,-4}} };
}
intmain()
{
std::数组
一个{std::数组{Goo{1,2},Goo{3,4},
std::数组{Goo{-1,-2},Goo{-3,-4}};
}
让我们通过一些吵闹的施工人员来确认:
struct Goo
{
Goo(int, int) { }
Goo(Goo &&) { std::cout << "Goo Moved." << std::endl; }
Goo(const Goo &) { std::cout << "Goo Copied." << std::endl; }
};
struct-Goo
{
Goo(int,int){}
Goo(Goo&&{std::cout不调用复制或移动构造函数是标准特别允许的优化(但不是必需的)
为了在编译器之间保持一致,实现必须检查构造函数是否可以被调用,如果它不想对其进行优化。请允许我用修改过的案例继续Bo的回答,同样在GCC 4.6中:
struct Goo
{
Goo(int x, unsigned int n) : x(x), s(new char[n]) { }
private:
Goo(const Goo &);
Goo(Goo &&);
int x;
char * s;
};
struct Foo
{
int a;
Goo g;
};
void f()
{
Foo k { 3, {1,2} }; // works
//Foo t { 1, Goo{5,6} }; // fails
//Foo r { 0, Goo(7,8) }; // fails
}
为什么没有可访问的复制/移动构造函数(注意,Goo
显然不是POD或聚合),第一种形式的就地构造仍然可以,但后两种形式(功能相同)表单不是吗?标准的哪一部分规定编译器必须在后两种情况下检查可访问的构造函数,而不是在第一种情况下检查?谢谢!我甚至不能让GCC用-O0
调用移动构造函数,不过——构造函数的选择取决于编译器,这不奇怪吗?顺便问一下,为什么可以我不是说array a{1,2},{3,4}
?说goog{1,2}完全可以
@Kerrek-构造就地优化非常简单,gcc即使在-O0也能做到这一点,这是众所周知的。Goo
有一个构造函数,它使用两个整数,所以它可以工作。std::array
只有它的默认构造函数,它不使用那种形式的值。它需要一个来自初始值设定项列表的构造函数我相信有一个“错误报告”。我认为std::array是显式设计为聚合类型的,因此它不能有任何用户定义的构造函数。我只是想知道,既然它是聚合,为什么我不能指定{1,2}
在聚合初始化中,让它调用匹配的构造函数a la 8.5.4第3条。@Kerrek-这是关于大括号省略(或缺少大括号省略)-例如,请参见。数组a{{{{1,2},{3,4}
应该可以工作,但显然gcc在这方面存在缺陷。@Johannes:我发布了一个后续——你是说后续场景和预期的一样,但是数组a{{{{1,2},{3,4}}}}
的失败是gcc中的一个缺陷吗?§8.5.4/3描述了为什么这是允许的。将其与§8.5/16/6/2进行对比。(对于延迟响应如何?;-)@伊尔贾恩:非常感谢,虽然摘录本可以更好,所以我不必切换任务!§8.5确实太大了——太大了,无法发表评论。--[@Ild贾恩:很好地引用了§8.5/16/6/2!所以fook{3,{1,2}
直接初始化k.a(3)
和k.g(1,2)
,而且我们不需要不可接受的复制构造函数。公平地说,litb也把这件事归功于我。:-]