简体   繁体   English

定义结构中向量的长度

[英]Defining the length of a vector within a struct

The struct I want to use is defined below. 我要使用的结构定义如下。 (I am using namespace std ): (我正在使用namespace std ):

struct body {string name; float m; vector< float > p; vector< float > v;};

This compiles, but later I get a segmentation fault at run time. 这样可以编译,但是后来我在运行时遇到了分段错误。 I know this is because the vectors don't have a defined size (I want three components). 我知道这是因为向量没有定义的大小(我需要三个分量)。

I have tried using the a vector constructor vector x(3,0) , but this won't compile. 我已经尝试使用向量构造函数vector x(3,0) ,但这将无法编译。 I get: 我得到:

glib.h(5): error: expected a type specifier
  struct body {string name; float m; vector<float> p (3,0); vector<float> v(3,0);};
                                                      ^

glib.h(5): error: expected a type specifier
  struct body {string name; float m; vector<float> p (3,0); vector<float> v(3,0);};
                                                        ^

glib.h(5): error: expected a type specifier
  struct body {string name; float m; vector<float> p (3,0); vector<float> v(3,0);};
                                                                            ^

glib.h(5): error: expected a type specifier
  struct body {string name; float m; vector<float> p (3,0); vector<float> v(3,0);};

Basically, I need to allocate space for a vector of 3 elements when I define the struct, and I do not know how to do this. 基本上,定义结构时,我需要为3个元素的向量分配空间,但我不知道该怎么做。 I am a C++ beginner and have done a lot of research, but I cannot find an answer. 我是C ++初学者,已经做了很多研究,但是找不到答案。 Thanks for any help I can get. 感谢您的任何帮助。

You call the vector constructor inside your constructor. 您可以在构造函数内部调用向量构造函数。

struct body {
    string name; 
    float m; 
    vector< float > p; 
    vector< float > v;

    body(): p(3,0), v(3,0) {}
};

You can specify the size for the vector in the constructor for your body : 您可以在body的构造函数中指定向量的大小:

struct body {
    string name; 
    float m; 
    vector< float > p; 
    vector< float > v;

     body() : p(3), v(3) {}
};

C++11 allows you to specify constructor arguments "in place", so something like: C ++ 11允许您“就地”指定构造函数参数,例如:

struct body {
    string name; 
    float m; 
    vector< float > p{3}; 
    vector< float > v{3};
};

...is allowed, but it sounds like your compiler doesn't support that (maybe time for an update?) ...是允许的,但听起来您的编译器不支持该功能(也许是时候进行更新了?)

Edit: doing a bit of checking, it appears that not all compilers select the correct constructor when given the second piece of code. 编辑:进行一些检查,当给出第二段代码时,似乎并非所有编译器都选择正确的构造函数。 For example, given the code above, VC++ gives a vector containing 3 0's, but g++ gives a vector containing a single value of 3. In other words, g++ is using the overload that takes an initializer list, but VC++ is using the overload that takes one parameter. 例如,给定上面的代码,VC ++给出了一个包含3个0的向量,而g ++给出了一个包含单个值3的向量。换句话说,g ++使用的是带有初始化程序列表的重载,而VC ++使用的是带有初始值列表的重载。接受一个参数。

For whatever it's worth, it appears that g++ is doing this correctly, and VC++ is incorrect 1 , but from a practical viewpoint it's of little consequence: code that uses it isn't portable, so most people probably want to avoid it (at least until the compiler vendors get their acts together). 不管值多少钱,g ++似乎都能正确执行,而VC ++是不正确的1 ,但是从实际的角度来看,这没有什么意义:使用它的代码不是可移植的,所以大多数人可能希望避免这样做(至少直到编译器供应商将他们的行为放在一起为止)。


  1. The specific wording is at $13.3.1.7: 具体文字为$ 13.3.1.7:

    • Initially, the candidate functions are the initializer-list constructors (8.5.4) of the class T and the argument list consists of the initializer list as a single argument. 最初,候选函数是类T的初始化器列表构造函数(8.5.4),参数列表由作为单个参数的初始化器列表组成。
    • If no viable initializer-list constructor is found, overload resolution is performed again, where the candidate functions are all the constructors of the class T and the argument list consists of the elements of the initializer list. 如果找不到可行的初始化器列表构造函数,则再次执行重载解析,其中候选函数是T类的所有构造器,并且参数列表由初始化器列表的元素组成。

std::vector has an intializer-list constructor, leaving on the question of whether it's viable. std::vector有一个初始化列表构造函数,剩下的问题是它是否可行。 That comes down to the question of whether converting 3 to a float is a "narrowing conversion". 这归结为以下问题:将3转换为float是否是“缩小的转换”。 In this case, the answer is no, it's not. 在这种情况下,答案是否定的,不是。 The official wording is (§8.5.4/7): 官方用语是(第8.5.4 / 7节):

A narrowing conversion is an implicit conversion 缩小转换是隐式转换

[ ... ] [...]

from an integer type or unscoped enumeration type to a floating-point type, except where the source is a constant expression and the actual value after conversion will fit into the target type and will produce the original value when converted back to the original type, 从整数类型或无作用域枚举类型到浮点类型,除非源是一个常量表达式,并且转换后的实际值将适合目标类型,并在转换回原始类型时会产生原始值,

So, since we're using a constant expression with the value 3 , and float is guaranteed to be able to hold that value, and produce 3 as the result if we convert it back to int , it's not a narrowing conversion. 因此,由于我们使用的值为3的常量表达式,并且保证float能够保留该值,并且如果将其转换回int ,则结果将生成3 ,这不是缩小的转换。 That means the initializer-list constructor is viable, so it's the one that should be chosen. 这意味着initializer-list构造函数是可行的,因此应该选择它。

In theory, if you want to do the in-place initialization, you should probably use: 从理论上讲,如果要执行就地初始化,则可能应使用:

std::vector<float> p{0, 0, 0};

...MS VC++, however, rejects this, reinforcing the previous advice that if you care about portability, you probably want to avoid this in general. ... MS VC ++拒绝了此建议,从而强化了先前的建议,即如果您关心可移植性,则通常可能希望避免这种情况。

You have a few options: 您有几种选择:

1) add a constructor to initialize the vectors to size 3: 1)添加一个构造函数以将向量初始化为大小3:

struct body 
{
  body() : p(3), v(3) {}
  string name; 
  float m; 
  vector< float > p; 
  vector< float > v;
};

2) initialize the variables at the point of declaration (C++11) 2)在声明时初始化变量(C ++ 11)

struct body 
{
  string name; 
  float m; 
  vector< float > p = vector<float>(3); 
  vector< float > v = vector<float>(3);
};

3) Use std::array<float, 3> instead of vectors 3)使用std::array<float, 3>代替向量

struct body 
{
  body() : p(3), v(3) {}
  string name; 
  float m; 
  std::array<float, 3> p; 
  std::array<float, 3> v;
};

3) Use brace initialization to instantiate the struct. 3)使用花括号初始化来实例化结构。

body b1 {"hello", 3.14, vector(3,0), vector(3,0) };

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM