此常见问题解答涉及聚合和POD,并涵盖以下材料:
假设我有一个类型,我想将其默认构造函数设为私有.我写了以下内容:
class C {
C() = default;
};
int main() {
C c; // error: C::C() is private within this context (g++)
// error: calling a private constructor of class 'C' (clang++)
// error C2248: 'C::C' cannot access private member declared in class 'C' (MSVC)
auto c2 = C(); // error: as above
}
Run Code Online (Sandbox Code Playgroud)
大.
但是,构造函数结果证明不像我想象的那样私密:
class C {
C() = default;
};
int main() {
C c{}; // OK on all compilers
auto c2 = C{}; // OK on …Run Code Online (Sandbox Code Playgroud) c++ default-constructor language-lawyer aggregate-initialization c++11
有时我不想提供默认构造函数,也不希望编译器为我的类提供系统默认构造函数.在C++ 11中,我可以这样做:
class MyClass
{
public:
MyClass() = delete;
};
Run Code Online (Sandbox Code Playgroud)
但目前我的讲师不允许我在我的任务中这样做.问题是:在C++ 11之前,有没有办法告诉编译器隐式提供默认构造函数?
我有一些误解:
让我们将struct A的默认构造函数标记为已删除:
struct A
{
A() = delete;
};
Run Code Online (Sandbox Code Playgroud)
下一条指令格式正确,有什么影响?:
A a{};
Run Code Online (Sandbox Code Playgroud)
1)如果T是没有默认构造函数的类类型,或者是用户提供的默认构造函数或者删除了默认构造函数,则该对象是默认初始化的.
但是然后默认初始化的效果是:
如果T是类类型,则调用默认构造函数以提供新对象的初始值.
或者它是聚合初始化?谢谢!
是否允许标准:
struct A
{
int a = 3;
int b = 3;
};
A a{0,1}; // ???
Run Code Online (Sandbox Code Playgroud)
这个课程仍然是聚合的吗?
clang接受此代码,但gcc不接受.
class B {
private:
friend class C;
B() = default;
};
class C : public B {};
class D : public B {};
int main() {
C {};
D {};
return 0;
}
Run Code Online (Sandbox Code Playgroud)
I assumed that since only class C is a friend of B, and B's constructor is private, then only class C is valid and D is not allowed to instantiate B. But that's not how it works. Where am I wrong with my …
请考虑以下代码:
#include <array>
struct T
{
T() = delete;
};
int main()
{
std::array<T, 0> a;
a.size();
}
Run Code Online (Sandbox Code Playgroud)
我们默认初始化一个0大小的数组.由于没有元素,因此不T应该调用构造函数.
但是,Clang仍然需要T默认构造,而GCC接受上面的代码.
请注意,如果我们将数组初始化更改为:
std::array<T, 0> a{};
Run Code Online (Sandbox Code Playgroud)
Clang这次接受了.
非默认构造是否可以T防止std::array<T, 0>默认构造?
我尝试了解@bolov对已删除默认构造函数问题的第一个公认答案。仍然可以创建对象...有时 [1]
似乎我在那儿发现了一个错误,因此弄乱了整个解释。
@bolov解释了为什么此代码成功用c ++ 11编译:
方案A
struct foo {
foo() = delete;
};
// All bellow OK (no errors, no warnings)
foo f = foo{};
foo f = {};
foo f{}; // will use only this from now on.
Run Code Online (Sandbox Code Playgroud)
以及为什么此代码无法在c ++ 11中编译:
方案C
struct foo {
foo() = delete;
foo(int) {};
};
foo f{}; // error call to deleted constructor
Run Code Online (Sandbox Code Playgroud)
他说,关键是第一个foo是集合,而第二个foo不是集合。
然后他给出了cppreference的摘录:
T类型的对象的列表初始化的影响是:...
- 如果T是聚合类型,则执行聚合初始化。这照顾了场景ABDE(以及C ++ 14中的F)
否则,将分两个阶段考虑T的构造函数:
所有采用std :: initializer_list的构造方法...
否则,T的所有构造函数都将参与重载解析[...],这将照顾到C(和C ++ 11中的F)...
根据摘录,当你写foo …
考虑以下代码:
struct S
{
int x;
double y = 1.1;
};
int main()
{
S s = {0};
}
Run Code Online (Sandbox Code Playgroud)
根据C++ 14标准,§8.5.1/ 7
如果列表中的初始化子条款少于聚合中的成员,则未明确初始化的每个成员应从其大括号或等号初始值初始化,或者,如果没有大括号或等号初始值,从空的初始化列表(8.5.4).
代码应该完全有效.
但是,g ++ 4.9.2拒绝代码(编译-std=c++14)
so.cpp:9:13: error: could not convert '{0}' from '<brace-enclosed initializer list>' to 'S'
S s = {0};
Run Code Online (Sandbox Code Playgroud)
另一方面,clang ++编译它.
这是g ++的已知问题吗?
这是有问题的代码示例:
struct A {
A() = delete;
};
int main()
{
// A a(); // compiles, since it's a function declaration (most vexing parse)
// A a; // does not compile, just as expected
A a{}; // compiles, why? The default constructor is deleted.
}
Run Code Online (Sandbox Code Playgroud)
在这里尝试使用任何可用的编译器.我尝试了几个,没有找到一个编译错误.