这有效:
int arr[10] = {};
Run Code Online (Sandbox Code Playgroud)
所有元素arr都被初始化为零.
为什么这不起作用:
std::array<int, 10> arr({});
Run Code Online (Sandbox Code Playgroud)
我从g ++(版本4.8.2)收到以下警告:
警告:缺少成员'std :: array <int,10ul> :: _ M_elems'的初始值设定项
考虑以下代码:
struct A
{
// No data members
//...
};
template<typename T, size_t N>
struct B : A
{
T data[N];
}
Run Code Online (Sandbox Code Playgroud)
这就是你必须如何初始化 B:B<int, 3> b = { {}, {1, 2, 3} };
我想避免基类不必要的空 {}。Jarod42 here提出了一个解决方案,但是,它不适用于元素默认初始化:B<int, 3> b = {1, 2, 3};很好,但B<int, 3> b = {1};不是:b.data[1]并且b.data[2]没有默认初始化为 0,并且会发生编译器错误。有什么方法(或者 C++20 会有)从构造中“隐藏”基类?
我主要尝试编写std::array. 但是,我对聚合初始化的规则(以及其他一些小细节)不太满意,因此不想使用它。
我不喜欢聚合初始化的事情:
struct A { int x,y; };
std::array< A, 2 > arr{1,2,3};
// produces A[0].x = 1, A[0].y = 2, A[1].x = 1, A[1].y = 0
Run Code Online (Sandbox Code Playgroud)
class B { B() = delete; };
B{}; // no compile time error
Run Code Online (Sandbox Code Playgroud)
到目前为止我所拥有的是以下内容:
#include <cstddef>
#include <type_traits>
#include <utility>
template< typename T, typename ... Ts >
inline constexpr bool areT_v = std::conjunction_v< std::is_same<T, Ts> ... >;
namespace ttt {
template< typename T, int N >
struct …Run Code Online (Sandbox Code Playgroud) 假设我有以下结构:
struct sampleData
{
int x;
int y;
};
Run Code Online (Sandbox Code Playgroud)
在使用时,我想将sampleData类型的变量初始化为已知状态.
sampleData sample = { 1, 2 }
Run Code Online (Sandbox Code Playgroud)
后来,我决定我需要在我的sampleDatastruct中存储更多数据,如下所示:
struct sampleData
{
int x;
int y;
int z;
};
Run Code Online (Sandbox Code Playgroud)
我的理解是,从我的预z数据结构遗留下来的两个字段初始化仍然是一个有效的语句,并将被编译.使用默认值填充缺少的字段.
这种理解是否正确?我最近一直在Ada工作,它也允许聚合初始化,但是它会将类似的问题标记为编译错误.假设我对上面的C++代码的假设是正确的,是否有一种语言结构可以将缺少的初始化值识别为错误?
struct S
{
int x;
int y;
};
std::atomic<S> asd{{1, 2}}; // what should this be? This doesn't work
Run Code Online (Sandbox Code Playgroud)
编辑:这两个{{1, 2}}和({1, 2})在G ++,在铛没有工作的工作.clang有解决方法吗?
c++ atomic aggregate-initialization uniform-initialization c++11
以下是Effective Modern C++(第55页)的引用:
"假设你使用一组空的大括号来构造一个支持默认构造函数的对象,并且还支持std :: initializer_list构造.你的空括号是什么意思?等规则是你得到默认构造."
我用std :: array尝试过这个:
std::array<int, 10> arr{};
Run Code Online (Sandbox Code Playgroud)
并得到了g ++(版本4.8.2)的警告:
警告:缺少成员'std :: array <int,10ul> :: _ M_elems'的初始值设定项
这是在尝试std::array从空构造一个时得到的警告std::initializer_list(请参阅为什么我可以从{}初始化一个常规数组,而不是std :: array来讨论此警告).
那么,为什么上面的代码行不能解释为调用默认构造函数?
我希望有人可以给我一些技术细节,说明为什么以下内容无法编译,如果可能的话,还有一个解决方法.
我有一个名为Foo的现有结构,以及使用初始化列表创建Foo实例的代码.此代码编译和工作:
struct Foo {
int id1;
int id2;
};
int main()
{
Foo f({1,2});
return f.id1;
}
Run Code Online (Sandbox Code Playgroud)
我希望Foo能够实现一个接口:
struct Interface {
// All pure virtual methods, but this won't compile even if empty
};
struct Foo : public Interface{
int id1;
int id2;
};
int main()
{
Foo f({1,2});
return f.id1;
}
Run Code Online (Sandbox Code Playgroud)
此代码不再编译,并且存在错误
cannot convert argument 1 from 'initializer list' to 'const _Ty &'
Run Code Online (Sandbox Code Playgroud)
(错误会根据您的确切编译器而改变.)
我发现有关聚合初始化的标准的这一部分:
[dcl.init.aggr]/1聚合是一个数组或类(第12条),1.1没有用户提供的,显式的或继承的构造函数(15.1),1.2没有私有或受保护的非静态数据成员(第14条) ),1.3没有虚函数(13.3),1.4没有虚拟,私有或受保护的基类(13.1).
虽然我不确定聚合初始化是否发生在这里.有人可以解释正在发生的错误,如果可能的话,可以提供我可以对界面进行的更改吗?我有几个需要这个接口的现有结构,以及许多使用这种形式的初始化的现有代码,我想尽可能少地重写它.谢谢!
在下面的代码中,使用模板参数推导来初始化A<T>对象,使用两种形式(根据大括号的类型不同):
template<typename T>
struct A{ T x; };
int main() {
static_assert( A{1}.x == 1 ); //#1: ok in GCC and MSVC
static_assert( A(1).x == 1 ); //#2: ok in GCC only
}
Run Code Online (Sandbox Code Playgroud)
第一种方式被 GCC 和 MSVC 接受,而第二种方式仅适用于 GCC,而 MSVC 打印错误:
error C2641: cannot deduce template arguments for 'A'
error C2780: 'A<T> A(void)': expects 0 arguments - 1 provided
error C2784: 'A<T> A(A<T>)': could not deduce template argument for 'A<T>' from 'int'
Run Code Online (Sandbox Code Playgroud)
演示: https: //gcc.godbolt.org/z/97G1acqPr
这是 MSVC 中的错误吗?
考虑以下代码:
#include <variant>
struct x {
int y;
};
int main() {
std::variant<x> v(std::in_place_type<x>, {3}); /*1*/
return std::get<x>(v).y;
}
Run Code Online (Sandbox Code Playgroud)
即使聚合初始化,这也不会编译,也不会{}从行中删除/*1*/
x a{3};
x b({3});
Run Code Online (Sandbox Code Playgroud)
适用于"类似构造函数"的形式.我可以以某种方式使std::variant初始化器知道使用聚合初始化构造结构的可能性,而不必为我的实际案例中可能使用的每个结构编写无聊的样板构造函数吗?
我希望这可以工作,不知何故,根据cppreference,有问题的两个重载(5)和(6)都说
使用指定的替代T构造变量并使用参数[...] 初始化包含的值
如果重要的话,我正在使用GCC 7.
C ++ 17对基类的聚合初始化很棒,但是当基数仅用于提供某些功能(因此没有数据成员)时,它很冗长。
这是最小的示例:
#include <cstddef>
struct base_pod
{
// functions like friend compare operator
};
template<typename T, std::size_t N>
struct der_pod : public base_pod
{
T k[N];
};
int main()
{
der_pod<int, 2> dp {{}, {3, 3} };
}
Run Code Online (Sandbox Code Playgroud)
如上面的示例所示,我必须提供empty {},否则将发生编译错误。现场演示。如果我忽略它:
prog.cc:15:28: error: initializer for aggregate with no elements requires explicit braces
der_pod<int, 2> dp{3, 3};
^
prog.cc:15:31: warning: suggest braces around initialization of subobject [-Wmissing-braces]
der_pod<int, 2> dp{3, 3};
^
{}
1 warning and 1 …Run Code Online (Sandbox Code Playgroud)