是否可以在我自己的默认ctor定义中调用聚合初始化?
GCC使用以下代码抱怨"错误:构造函数委托给自己":
struct X {
int x, y, z, p, q, r;
X(): x{}, y{}, z{}, p{}, q{}, r{} { } // cumbersome
//X(): X{} { } // the idea is nice but doesn't compile
};
Run Code Online (Sandbox Code Playgroud)
我现在正在使用memset(this, 0, sizeof(*this))ctor身体.
c++ constructor aggregate-initialization c++11 delegating-constructor
在Win32标准库中,使结构的第一个成员成为结构的大小是一个相当普遍的习惯用法,如下所示:
#include <cstddef>
struct wrapped_float
{
std::size_t value; //Initialize with sizeof(wrapped_float)
float other; //Actual info
};
Run Code Online (Sandbox Code Playgroud)
如果我创建一个全局对象,那么有一个简单的初始化语法可以自动适应以下类型的更改a:
constexpr wrapped_float const a{ sizeof(a), 0 }; //OK
Run Code Online (Sandbox Code Playgroud)
我希望我的对象不是结构的静态成员,而不是创建全局对象:
struct test1 {
static constexpr wrapped_float const b{ sizeof(b), 0 }; //Error!
};
Run Code Online (Sandbox Code Playgroud)
但是MSVC在此类代码上出错,抱怨b不是的成员struct test1。因此,我有两个相关的问题:
1.为什么全局成员和静态成员之间有区别?
2.有解决方法吗?
有问题的类型来自Win32标头,因此我无法从中添加或删除成员wrapped_float。(如果有用,我可以使用派生的类/结构。)
的明显变化
struct test2 {
static constexpr wrapped_float const b{ sizeof(test::b), 0 };
};
Run Code Online (Sandbox Code Playgroud)
和
struct test3 {
static constexpr wrapped_float const b{ sizeof(decltype(b)), 0 };
};
Run Code Online (Sandbox Code Playgroud)
产生相同的结果。我已经在Godbolt …
我对我编写的 (C++14) 代码片段感到困惑:
struct B {};
struct C { int m; };
struct D : B { int m; };
int main() {
C c = { 1 }; // this works
D d = { 1 }; // this doesn't work
}
Run Code Online (Sandbox Code Playgroud)
我可以为D自己编写一个构造函数,但是我找不到一个很好的解释来解释为什么该结构D不再可以使用初始化列表进行初始化。我所改变的只是让它继承一个完全空的类——我想我以某种方式让它的行为不像结构体。
C我的编译器究竟如何以不同的方式处理结构D?
我正在观看由Jason Tuner在youtube上播放的视频系列,并在此处发现的这个特定视频:聚合初始化他开始使用clang ++ c ++ 03然后将编译器更改为clang ++ c ++ 11然后当他合并基类层次结构时他改变了它使用c ++ 17或c ++ 1z使用最近的clang ++构建.
我刚刚下载并安装了MSVS2017RC,我在Intel Quad Core Extreme上运行Windows 7 64bit SP1.
但是当我在我的IDE中尝试跟踪他的视频时
struct B {
double q;
};
struct S : B {
int i;
float f;
};
int main() {
S s{ {}, 1, 2.3f };
return s.f;
}
Run Code Online (Sandbox Code Playgroud)
我收到此编译器错误:
1>------ Build started: Project: Test1z, Configuration: Debug Win32 ------
1>stdafx.cpp
1>Test1z.cpp
1>c:\users\skilz80\documents\visual studio 2017\projects\test1z\test1z\test1z.cpp(15): error C2440: 'initializing': cannot convert from 'initializer list' to 'S'
1>c:\users\skilz80\documents\visual studio …Run Code Online (Sandbox Code Playgroud) c++ visual-c++ aggregate-initialization c++17 visual-studio-2017
我有以下示例:
#include <array>
struct A {
const char* str;
const char* str2;
};
template<size_t N>
struct As {
std::array<A,N> elems_;
};
template<class... Args>
As(Args...)->As<sizeof...(Args)>; //<-- NOTE: deduction guide !
constexpr static As as{A{"a","b"}, A{"1","2"}};//<-- 'retyping' A here
int main() {
return as.elems_.size();
}
Run Code Online (Sandbox Code Playgroud)
尽管此代码有效,但我想避免在A汇总列表中对的“重新键入” ,但是如果不加说明,则推导指南将失败:("cannot deduce template arguments for 'As'"我想这很有意义)。解决此问题的一种方法可能是通过手写我需要的任意数量的扣除指南,此后我可以A在每个扣除指南中编写类型(即:针对我需要的每种尺寸的容器进行一次扣除)。
c++ language-lawyer aggregate-initialization constexpr c++17
我一直认为聚合初始化是为了让编码人员免于编写自定义构造函数。然而,这似乎“潜入”了私有构造函数的“安全旁路”。
假设我有class A一个我只想由 来创建的东西class B。
struct A
{
friend class B;
const int i, k;
private:
A () = default;
};
class B
{
public:
A what () { return {1, 2}; }
};
int main ()
{
B b {};
A a {2,3}; // oh no
return 0;
}
Run Code Online (Sandbox Code Playgroud)
上面的示例编译并运行良好,并且通过使用大括号,我可以非常轻松地A在任何地方创建对象。
防止这种情况的唯一方法是编写一个用户构造函数,然后完全取消聚合初始化。
所以我的问题是:聚合初始化是默认的“隐藏public”构造函数吗?
实例: https: //onlinegdb.com/r1jHLxzRD
没有答案的类似问题:私有聚合初始化
C++20 引入了对指定初始值设定项的支持。
在 g++ with 中-std=c++17,可以使用指定的初始值设定项,只要您不遗漏任何初始值设定项,它将编译而不会出现任何错误或警告:
struct Foo {
int a;
float b;
};
Foo f {
.a = 7,
.b = 42.1f,
};
Run Code Online (Sandbox Code Playgroud)
然而,如果我启用-Wpedantic(并且-Werror)C++17 编译器会输出:
error: C++ designated initializers only available with '-std=c++20' or '-std=gnu++20' [-Werror=pedantic]
Run Code Online (Sandbox Code Playgroud)
但似乎没有一种方法可以在不禁用的情况下禁用或抑制此错误-Wpedantic,这对我来说太粗糙了。
我发现这非常令人困惑,因为在 C++17 中使用此功能时没有发出警告 - 使用它的代码将编译并运行,看似具有未定义的行为,但从我在网上找到的所有内容来看,不应该使用它使用 C++17。
那么,为什么在不 使用 C++17 的情况下使用此不受支持的功能时不会出现警告或错误呢-Wpedantic?如果它在技术上是 UB 的,那么警告用户不支持的语言功能肯定不是迂腐的吗?如果不是 UB,那么它就可以工作,对吗?
-Wpedantic最后,如果我选择在 C++17 代码中使用指定的初始值设定项,那么在不重新编译 g++ 的情况下,如何欺骗编译器接受而不生成此类警告?
typedef struct node {
int val;
int val2;
node(int a, int b) : val(a), val2(b) {}
node(int val) = delete;
}node;
int main()
{
node a = {3};
cout << a.val << " " << a.val2 << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
上面的代码给出了编译错误,表明使用了已删除的函数node::node(int)。
但是,当我删除 时node(int a, int b) : a(val), b(val2) {},这段代码编译没有问题。这怎么会发生呢?
c++ initialization aggregate-initialization list-initialization c++20
例如,给定结构S:
typedef struct {
int a, b;
} S;
Run Code Online (Sandbox Code Playgroud)
...以及一个带指针的方法S,我可以在一行中为它分配聚合初始值设定项1的值吗?这是我使用临时的现有解决方案:
void init_s(S* s) {
S temp = { 1, 2 };
*s = temp;
}
Run Code Online (Sandbox Code Playgroud)
我正在使用C11.
1对于那些不了解我的问题的非常罕见的超级学生,因为不知何故"聚合初始化器"在这里不适用,因为LHS没有声明一个新对象,我的意思是"聚合初始化器一样的语法与括号和东西".
c compound-literals assignment-operator aggregate-initialization c11
我在 Vulkan 教程中看到了以下代码:
VkImageMemoryBarrier imageMemoryBarrier = {
.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT,
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT,
.oldLayout = VK_IMAGE_LAYOUT_GENERAL,
.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
/* .image and .subresourceRange should identify image subresource accessed */
};
Run Code Online (Sandbox Code Playgroud)
如果我只列出了没有成员 '.member_name =' 的枚举,那将是聚合初始化,对吗?但这叫什么?这个类在 .srcAccreasMask 之前还有其他成员,我假设所有其他没有提到的成员都是零初始化的?但是如果我不知道它叫什么,就很难查到它。另外,我记得像这样的东西是一个新的 C 特性,但它在 Visual Studio 中为我用 C++ 编译。这是一个 C++ 特性,对吧?
c c++ initialization designated-initializer aggregate-initialization
c++ ×9
c++17 ×3
c ×2
c++20 ×2
c++11 ×1
c11 ×1
constexpr ×1
constructor ×1
friend ×1
inheritance ×1
private ×1
sizeof ×1
struct ×1
visual-c++ ×1