标签: stdinitializerlist

为什么允许 std::initializer_list 不指定大小并同时分配堆栈?

我从这里了解到不需要std::initializer_list分配堆内存。这对我来说很奇怪,因为您可以在不指定大小的情况下获取std::initializer_list对象,而对于数组,您始终需要指定大小。尽管初始化器列表在内部几乎与数组相同(正如帖子所暗示的那样)。

我很难理解的是,C++ 作为静态类型语言,每个对象的内存布局(和大小)必须在编译时固定。因此,每个std::array都是另一种类型,我们只是从通用模板中生成这些类型。但对于std::initializer_list,此规则显然不适用,因为接收函数或构造函数不需要考虑内存布局(虽然它可以从传递给其构造函数的参数派生)。仅当类型堆分配内存并且仅保留存储来管理该内存时,这对我才有意义。那么差异就很像std::arrayand std::vector,对于后者,您也不需要指定大小。

std::initializer_list不使用堆分配,正如我的测试所示:

#include <string>
#include <iostream>

void* operator new(size_t size)
{
    std::cout << "new overload called" << std::endl;    
    return malloc(size);
}


template <typename T>
void foo(std::initializer_list<T> args)
{
    for (auto&& a : args)
    std::cout << a << std::endl;
}

int main()
{
    foo({2, 3, 2, 6, 7});

    // std::string test_alloc = "some string longer than std::string SSO";
} …
Run Code Online (Sandbox Code Playgroud)

c++ types heap-memory stack-memory stdinitializerlist

19
推荐指数
3
解决办法
1966
查看次数

std :: initializer_list构造函数

在这样的代码中:

#include <iostream> 
#include <initializer_list>
#include <string>

struct A 
{
  A() { std::cout << "2" << std::endl; }
  A(int a) { std::cout << "0" << std::endl; }
  A(std::initializer_list<std::string> s) { std::cout << "3" << std::endl; }
  A(std::initializer_list<int> l) { std::cout << "1" << std::endl; } 
};

int main() 
{ 
 A a1{{}}; 
} 
Run Code Online (Sandbox Code Playgroud)

为什么调用std::initializer_list<int>构造函数的规范?如果我们定义构造函数,它会产生歧义编译错误std::initializer_list<double>.这种结构的规则是什么?为什么std::initializer_list数字作为模板参数如此具体?

c++ object-construction c++11 stdinitializerlist

12
推荐指数
2
解决办法
2030
查看次数

为什么我们需要 std::initializer_list 的私有构造函数?

的建议实施std::initializer_list标准C ++编程语言很简单。简单我的意思是没有什么奇怪的。
但是在 Compilers 的实现中事情变得复杂std::initializer_list,例如,GCC 有一个私有构造函数 for std::initializer_list,上面有一条注释说:'编译器可以调用私有构造函数。'。在这里eerorika回答:std::initializer_list是特别的。所以我在编译器源代码中寻找它:

铛:

海湾合作委员会:

我不明白为什么我们需要一个特殊的私有构造函数?前段时间我想转换std::vector<T>std::initializer_list<T>.

c++ stdinitializerlist

12
推荐指数
1
解决办法
167
查看次数

constexprinitializer_list 使用 MSVC 不产生输出

以下程序在 GCC 和 Clang 中编译时不会发出警告,并产生预期的输出:

#include <initializer_list>
#include <iostream>

constexpr std::initializer_list<std::initializer_list<const char*>> list = {
    {"a", "b", "c"},
    {"d"}
};

int main() {
    for (const auto& outer: list) {
        std::cout << "level:\n";
        for (const auto& inner: outer) {
            std::cout << "  " << inner << "\n";
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然而,使用 MSVC,该程序根本不会产生任何输出。

根据 C++ 标准,该程序有效吗?这是 MSVC 中的错误吗?如果这不是有效的 C++ 那么为什么 GCC 或 Clang 没有发出警告?有没有更好的方法来创建constexpr内部列表没有固定大小的嵌套列表?

c++ language-lawyer stdinitializerlist

11
推荐指数
1
解决办法
215
查看次数

为什么这个initializer_list在传递字符串时会出现异常?

我已经尝试了我的G ++版本的C++ 0x初始化列表实现,但它只输出空行.

#include <initializer_list>
#include <iostream>
#include <string>

int main() {
  std::initializer_list<std::string> a({"hello", "stackoverflow"});
  for(auto it = a.begin(), ite = a.end(); it != ite; ++it)
    std::cout << *it << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

我不知道我做错了什么.有人可以帮帮我吗?

c++ iterator c++11 stdinitializerlist

9
推荐指数
1
解决办法
1520
查看次数

将可变列表类型的扩展打包到复杂类型的初始化列表中 - 这是合法的吗?

我想将一个可变参数类型列表"实现"到相关值的initializer_list中.例如,有std::tuple几个std::integral_constant<T, x>得到一个std::initializer_list<T>{...}.一般情况下,我想得到一些复杂类型的initializer_list,比如std::string.

但是下面这个简单的例子让我在Clang编译时崩溃了(虽然它适用于GCC,至少在Coliru上),所以我怀疑UB(或Clang中的bug):

template <class... Ts>
std::initializer_list<const std::string> materialize()
{
    return {
      std::to_string(Ts::value)...
    };
}

void print_out()
{
   for (const auto & x : materialize<std::true_type, std::false_type>()) {
      std::cout << x << "\n";
   }
}
Run Code Online (Sandbox Code Playgroud)

住在Coliru

那么,这样的代码合法吗?在C++ 11/14/17中?

c++ c++11 c++14 stdinitializerlist c++17

8
推荐指数
1
解决办法
249
查看次数

std::initializer_list 什么时候可以是 constexpr?

根据 cppreference.com,std::initializer_lists 具有constexpr 构造函数constexpr 大小方法(C++14 起)。

尽管我使用的编译器似乎同意 constexpr 初始值设定项列表的大小确实是 constexpr,但在某些情况下,它不相信我的列表是 constexpr。由于 std::initializer_lists 可能涉及一些“编译器魔法”,我开始想知道 constexpr 是否不适用于它们,其方式与适用于非魔法对象的方式完全相同。

我跳到 Compiler Explorer 上,发现主要编译器在这个主题上并不一致

那么以下四种情况的正确行为(根据标准)是什么?

#include <initializer_list>

using size_type = std::initializer_list<int>::size_type;

template <typename T>
size_type Foo(std::initializer_list<T> const &list) {
    return list.size();
}

int main() {
    // 1.  Example based on
    // https://en.cppreference.com/w/cpp/utility/initializer_list/size
    // gcc: works
    // clang: no viable c'tor or deduction guide
    // msvc: works
    static_assert(std::initializer_list{1, 2, 3}.size() == 3);

    // 2.  Make a constexpr std::initializer_list<T> with T …
Run Code Online (Sandbox Code Playgroud)

c++ language-lawyer constexpr stdinitializerlist c++20

8
推荐指数
1
解决办法
179
查看次数

同样的叮当声,std::initializer_list 程序与 -std=c++14/-std=c++17 的结果不同

首先,这是一个好奇的问题,我永远不会在现实生活中编写这样的代码。

以下代码与 -O3 -std=c++14 和 -O3 -std=c++17 标志的行为不同,在 C++14 中,我得到了错误的分配,我推测是从垃圾 std::string 的复制构造:

#include<algorithm>
#include<numeric>
#include<vector>
#include<string>
#include<iostream>

using namespace std;
static auto results = std::initializer_list<string>{"1                               ",
"2"};
string f() {

    auto result = std::accumulate(results.begin(), results.end(), string(""));
    return result;

}

int main()
{
    return f().size();
}
Run Code Online (Sandbox Code Playgroud)

https://godbolt.org/z/H-Xzei

我的猜测是 C++17 版本比 C++14 版本保持底层数组的存活时间更长,但我发现 cppreference 上的初始化列表从 C++14 到 C++17 没有相关变化,所以我很困惑。这只是 UB 是 UB,还是语言发生了变化?

PS我知道如何解决这个问题,使用static const auto& results作品,就像之前提到的,这只是一个关于语言极端情况的问题。

c++ clang language-lawyer stdinitializerlist c++17

7
推荐指数
1
解决办法
126
查看次数

使用{a,b,c}作为参数或{a,b,c}实际执行的构造函数

我知道,我可以像这样初始化数据.

int array[3] = { 1, 2, 3 };
Run Code Online (Sandbox Code Playgroud)

甚至

int array[2][2] = { {1, 2}, {3, 4} };
Run Code Online (Sandbox Code Playgroud)

我也可以这样做 std::vector

std::vector<int> A = { 1, 2, 3 };
Run Code Online (Sandbox Code Playgroud)

假设我想写自己的课程:

class my_class
{
     std::vector< int > A;
     public:
     //pseudo code
           my_class(*x) { store x in A;} //with x={ {1, 2}, {3, 4} }
     // do something
};
Run Code Online (Sandbox Code Playgroud)

是否可以编写这样的构造函数,它是如何可能的?这是什么声明

{{1, 2}, {3, 4}} 实际上在做.

我总是发现,你可以用这种方式初始化数据,但绝不是它正在做的事情.

c++ constructor class c++11 stdinitializerlist

6
推荐指数
1
解决办法
208
查看次数

仅移动对象的 std::vector 的支撑初始化失败

我可以简洁地(用大括号)初始化以下 6 种情况中的 5 种:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n
可复制的只移动的
大批是的是的
标准::数组是的是的
std::向量是的
\n
\n

一种似乎不起作用的情况是尝试初始化仅移动对象的 std::vector ;无法编译,并显示消息,例如:“错误:调用 \'std::unique_ptr\' 的隐式删除复制构造函数”。

\n

为什么是这样?是否有适用于这种情况的替代初始化语法?

\n

下面的程序演示了。

\n
/*\nclang++ -std=c++14 -W -Wall -Werror question.cc -o question\nclang++ -std=c++17 -W -Wall -Werror question.cc -o question\nclang++ -std=c++20 -W -Wall -Werror question.cc -o question\nclang++ -std=c++2b -W -Wall -Werror question.cc -o question\ng++ -std=c++14 -W -Wall -Werror question.cc -o question\ng++ -std=c++17 -W -Wall -Werror question.cc -o question\ng++ -std=c++20 -W -Wall -Werror question.cc -o …
Run Code Online (Sandbox Code Playgroud)

c++ stdvector stdinitializerlist braced-init-list

6
推荐指数
1
解决办法
130
查看次数