想象一下,你有一个简单的矩阵类
template <typename T = double>
class Matrix {
T* data;
size_t row, col;
public:
Matrix(size_t m, size_t n) : row(m), col(n), data(new T[m*n]) {}
//...
friend std::ostream& operator<<(std::ostream& os, const Matrix& m) {
for (int i=0; i<m.row; ++i) {
for (int j=0; j<m.col; ++j)
os<<" "<<m.data[i + j*m.row];
os<<endl;
}
return os;
}
};
Run Code Online (Sandbox Code Playgroud)
有没有办法用初始化列表初始化这个矩阵?我的意思是从初始化列表中获取矩阵和元素的大小.类似下面的代码:
Matrix m = { {1., 3., 4.}, {2., 6, 2.}};
Run Code Online (Sandbox Code Playgroud)
会打印
1 3 4
2 6 2
Run Code Online (Sandbox Code Playgroud)
期待您的回答.谢谢你们.AA
编辑
所以我研究了你的建议来制作一个使用初始化列表初始化元素的通用数组.但这是我能获得的最通用的.如果你们中的任何人有任何建议可以使它成为一个更通用的课程,我将不胜感激.还有几个问题:
我在VC++ 2010中编写了这个程序:
class class1
{
public:
class1 (initializer_list<int> a){};
int foo;
float Bar;
};
void main()
{
class1 c = {2,3};
getchar();
}
Run Code Online (Sandbox Code Playgroud)
但是当我编译项目时我得到这个错误:
错误1错误C2552:'c':无法使用初始化程序列表初始化非聚合c:\ users\pswin\documents\visual studio 2010\projects\test_c ++ 0x\test_c ++ 0x\main.cpp 27
和
2 IntelliSense:对于类型为"class1"的对象,不允许使用"{...}"进行初始化c:\ users\pswin\documents\visual studio 2010\projects\test_c ++ 0x\test_c ++ 0x\main.cpp 27
问题是什么?
我发现对类使用初始化列表语法的可能性取决于类字段是否具有默认值.为什么?
确切地说,请考虑以下代码:
class S
{
public:
int a;
};
...
int a;
S s{ a };
Run Code Online (Sandbox Code Playgroud)
它编译没有任何问题.但是如果我在类字段中添加一个默认值,它就会停止构建:
class S
{
public:
int a = 0;
};
...
int a;
S s{ a };
Run Code Online (Sandbox Code Playgroud)
错误1错误C2440:'初始化':无法从'initializer-list'转换为'S'
为什么?还有什么影响这样的构造函数生成?
我有以下代码:
#include <initializer_list>
#include <utility>
enum class Classification
{
Unspecified,
Primary,
Secondary
};
class ClassificationMap
{
public:
ClassificationMap(std::initializer_list<std::pair<const Classification, int>> content = {});
};
void foo(ClassificationMap) {}
int main()
{
foo({{Classification::Unspecified, 42}});
}
Run Code Online (Sandbox Code Playgroud)
Visual Studio 2013和2017以及Clang 3.4.1(及以上版本)都编译好了代码.从我的POV来看,它也应该没问题.但是,GCC 5.1拒绝编译它,并出现以下错误:
<source>: In function 'int main()':
<source>:22:44: error: could not convert '{{Unspecified, 42}}' from '<brace-enclosed initializer list>' to 'ClassificationMap'
foo({{Classification::Unspecified, 42}});
Run Code Online (Sandbox Code Playgroud)
(我将正确的标准flag(-std=c++11)传递给GCC和Clang).
我的代码中是否存在问题,或者这实际上是GCC错误?
补充信息:在我的实际代码中,初始化列表用于初始化类的无序映射成员ClassificationMap(这就是它的类型就是它的原因).我需要代码在VS2013和GCC 5.1中工作
std::vector 可以初始化为
std::vector<std::string> words1 {"the", "frogurt", "is", "also", "cursed"};
Run Code Online (Sandbox Code Playgroud)
现在,如果想要为我的某个类型实现类似的功能,我该如何去做呢?我该如何实现此功能的构造函数?
标准如何支持我实现这一目标(参考标准将是最有帮助的)?基本上,如果你可以教我如何实现std::vector它就足够了.
这可以在C++ 11之前完成吗?
另外,我可以使用POD结构类型初始化列表,以便我可以使用不同类型的值来初始化我的类型吗?
在我的项目中,我将使用过的点类型更改Eigen::Vector2f为Eigen::Vector2d并遇到了对齐问题.
这是代码的简化版本:
#include <vector>
#include <Eigen/Eigen>
int main()
{
std::vector<Eigen::Vector2d> points = { {0,0}, {0,1} };
}
Run Code Online (Sandbox Code Playgroud)
我收到以下运行时错误:
eigen3/Eigen/src/Core/DenseStorage.h:78: Eigen::internal::plain_array<double, 2, 0, 16>::plain_array() [T = double, Size = 2, MatrixOrArrayOptions = 0, Alignment = 16]: Assertion `(reinterpret_cast<size_t>(array) & 0xf) == 0 && "this assertion is explained here: " "http://eigen.tuxfamily.org/dox-devel/group__TopicUnalignedArrayAssert.html" " **** READ THIS WEB PAGE !!! ****"' failed.
Run Code Online (Sandbox Code Playgroud)
正如断言消息所示,我读到了固定大小的可矢量化特征对象所需的对齐.还有关于STL容器的小节.似乎我有两个选择:
Eigen::aligned_allocatorEIGEN_DEFINE_STL_VECTOR_SPECIALIZATION宏.两次尝试都不编译(使用GCC 4.8.3和Clang 3.5进行测试),因为编译器无法正确转换初始化列表.
这里改变了代码:
#include <vector> …Run Code Online (Sandbox Code Playgroud) 我有这样的情况:
class A {
public:
A() : n(0) {}
private:
int n;
int m;
}
Run Code Online (Sandbox Code Playgroud)
m在构造函数中初始化的应用程序逻辑中没有任何意义.但是,Eclipse警告我构造函数m未初始化.我现在无法在其他地方运行代码.警告是:
成员'm'未在此构造函数中初始化
那么,C++是否鼓励我们初始化构造函数中的所有数据成员,或者它只是Eclipse的逻辑?
从/sf/answers/1863048911/可以看出,标准保证以下标题#include <initializer_list>:
<utility><string><algorithm><random><valarray><regex>这些头文件中的大多数都声明了至少一个带std::initializer_list<E>参数的函数,所以它是有意义的.然而,
<array>,<stack>并且<queue>没有这样的功能,尽管在这里统一处理所有容器也许是有意义的.<utility> 没有这样的功能.<iterator>确实有一个带initializer_list参数(rbegin,rend)的函数,但它没有指定包含<initializer_list>.这些例外背后的理由是什么?
可以使用所谓的初始化列表来初始化数组。
例如:
int my_array[3] = {10, 20, 30};
Run Code Online (Sandbox Code Playgroud)
当我们为数组设置一组初始值时,这非常有用。但是,这种方法一旦声明就无法为数组分配新值。
my_array = {10, 20, 30};
error: assigning to an array from an initializer list
Run Code Online (Sandbox Code Playgroud)
但是,有时我们有一些过程需要将数组初始化为一些初始值(例如,在循环内),因此我认为能够使用初始化列表将值分配给已声明的变量将非常有用。
我的问题是:是否有理由在声明时拥有这种功能,但一旦声明数组就没有?为什么在一种情况下有效,而在另一种情况下无效?
#include <vector>
int main()
{
auto v = std::vector{std::vector<int>{}};
return v.front().empty(); // error
}
Run Code Online (Sandbox Code Playgroud)
看在线演示
然而,根据 Scott Meyers 的Effective Modern C++(强调原文):
但是,如果一个或多个构造函数声明了一个类型为 的参数
std::initializer_list,则使用花括号初始化语法的调用强烈倾向于采用 的重载std::initializer_lists。强烈。如果编译器有任何方法可以将使用花括号初始化器的调用解释为采用 a 的构造函数std::initializer_list,则编译器将采用该解释。
所以,我认为std::vector{std::vector<int>{}};应该产生一个对象std::vector<std::vector<int>>而不是std::vector<int>.
谁错了?为什么?
c++ ×10
initializer-list ×10
c++11 ×7
arrays ×1
c++17 ×1
ctad ×1
eclipse ×1
eigen3 ×1
gcc ×1
nested-lists ×1
visual-c++ ×1