问题描述
我有以下类定义.我提供了一个私有的 x
来确保它不是聚合的.
I have the following class definition. I included a private x
to make sure it is not an aggregate.
class A {
private:
int x;
public:
A() = delete;
A(std::initializer_list<int>) { printf("init\n"); }
};
现在,如果我使用 A a = A {}
初始化此对象,它将说 A :: A()
被删除.我猜它正在尝试调用 A :: A()
,但是它已被删除.如果我注释掉该行,则会自动生成 A :: A()
.然后,如果我运行此代码,我可以看到它正在调用 A :: A(std :: initializer_list< int>)
!
Now if I initialize this object with A a = A{}
, it will say A::A()
is deleted. I guess it is trying to call A::A()
but it is deleted. If I comment out that line, so A::A()
is automatically generated. Then if I run this code, I could see that it is calling A::A(std::initializer_list<int>)
!
更令人困惑的是,如果我定义 A()= default
,则初始化会再次调用 A :: A()
.
And more confusing, if I define A() = default
, the initialization calls A::A()
again.
有人能指出我正确理解这种行为的正确方向吗?谢谢!
Can anyone point me to the right direction of understading this behavior? Thanks!
我正在使用带有标志 -std = c ++ 17
的G ++ 6.3.0.
I'm using G++ 6.3.0 with flag -std=c++17
.
推荐答案
行为正确.
首先:
// Calling
A a = A{}; // equals A a = A();,
是列表初始化习惯用法的方便统一.请参阅: https://stackoverflow.com/a/9020606/3754223
which was a convenience uniformization of the list-initialization idiom.Refer to: https://stackoverflow.com/a/9020606/3754223
class A {
private:
int x;
public:
**A() = delete;**
A(std::initializer_list<int>) { printf("init\n"); }
};
如上所述,A a = A {}将是... = A(),将其删除.
As said above, A a = A{} will be ... = A(), which is deleted.
class A {
private:
int x;
public:
A(std::initializer_list<int>) { printf("init\n"); }
};
在这种情况下,没有提供默认的构造函数,因为您已定义了initializer-list构造函数.因此{}被隐式转换为空的初始值设定项列表!
In this case, there's no default constructor provided, since you have your initializer-list constructor be defined. Consequently {} is converted to an empty initializer list implicitely!
class A {
private:
int x;
public:
**A() = default;**
A(std::initializer_list<int>) { printf("init\n"); }
};
在这种情况下,可以使用空的默认构造函数,并将A {}转换回A(),使其被调用.
In this case the empty default constructor is available and A{} is converted back to A(), causing it to be called.
请参阅以下页面并对其进行详尽的阅读. http://en.cppreference.com/w/cpp/utility/initializer_list http://en.cppreference.com/w/cpp/language/value_initialization
Please refer to the below pages and get a thorough read into it.http://en.cppreference.com/w/cpp/utility/initializer_listhttp://en.cppreference.com/w/cpp/language/value_initialization
使用:
A a = {{}};
将导致总是初始化构造器列表构造函数被调用,因为外面的花括号表示初始化列表,而内部的括号表示零构造元素.->非空的初始值设定项列表...(请再次参见上方的stackoverflow链接!)
Would cause that ALWAYS the initializer-list constructor is called, as the outer-curly-brackets denoted the init-list, and the inner a zero-constructed element. -> Non-empty initializer-list... (See stackoverflow link above again!)
顺便说一句,考虑到这是一个非常棘手的部分,我不明白为什么这个问题被否决了...
And btw, I cannot understand why the question is downvoted, considering that this is a really tricky part...
这篇关于使用已删除的默认构造函数的C ++直接列表初始化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!