【问题标题】:Initialize vectors size in array of objects初始化对象数组中的向量大小
【发布时间】:2017-08-03 18:23:50
【问题描述】:

我想初始化对象数组中向量的大小。

每个向量都有相同的大小,所以...

LIB 文件:

#include <vector>

Class NameClass
{
 public:
  explicit NameClass( unsigned size )
  {
    vectorName.resize( size );
  }

  std::vector <type> vectorName;
};

主文件:

#include "lib.hpp"

int main( void )
{
  NameClass object( size ); #1

  NameClass object[ number_objects ]( size ); #2
  NameClass object[ number_objects ] = {NameClass(size), NameClass(size), ... }; #3

  return 0;
}

#1 有效,但不是数组, #2没有,编译器说“要求从int转换为非标量类型'NameClass'” 并且#3有效,但是......初始化每个对象只是荒谬的。而且我不能只在类中放置一个静态大小,因为值会发生变化。

所以...我的研究表明我需要使用 std::generate。问题是……最好的方法是什么?

对不起,如果是简单的问题如何使用 std::generate 我是初学者,很难找到最佳解决方案。

有些人建议复杂的解决方案,但我继续使用我的解决方案

#include "lib.hpp"

int main( void )
{
  unsigned number_objects = something;
  unsigned size = other_thing;
  NameClass object[ number_objects ];

  for( unsigned i = 0; i < number_objects; i++)
    object[i].vectorName.resize( size );

  return 0;
}

我使用 Thins 是因为它确实易于理解,并且有效。但我对其他易于理解和实用的解决方案持开放态度。

link std::generate

【问题讨论】:

标签: c++ arrays c++11 vector


【解决方案1】:

您必须初始化每个向量,这就是您在代码中呈现它的方式。你可以这样做

std::vector<NameClass> classes(number_of_objects);
std::generate(classes.begin(), classes.end(), []{return NameClass(size);});

std::generate 将为向量的每个元素初始化一个 NameClass 的实例。

【讨论】:

  • g++ class-main.cpp 有问题。在 class-main.cpp:4:0 中包含的文件中:class.hpp:7:12: 注意:候选人:NameClass::NameClass(unsigned int) 显式 NameClass(unsigned size) ^~~~~~~~~ 类.hpp:7:12: 注意:候选人需要 1 个参数,0 提供类。hpp:4:7: 注意:候选人:NameClass::NameClass(const NameClass&) 类 NameClass ^~~~~~~~~
  • 如果您使用std::vector,只需使用std::vector&lt;NameClass&gt; classes(number_of_objects, NameClass(size));
【解决方案2】:

如果你愿意使用std::array和C++14,我们得到:

template<std::size_t...Is>
auto index_over( std::index_sequence<Is...> ) {
  return [](auto&&f)->decltype(auto) {
    return decltype(f)(f)(std::integral_constant<std::size_t, Is>{}...);
  };
}
template<std::size_t N>
auto index_upto( std::integral_constant<std::size_t, N> ={} ) {
  return index_over( std::make_index_sequence<N>{} );
}

template<std::size_t N, class F,
  class T = std::decay_t<std::result_of_t< F&( std::integral_constant<std::size_t, 0>& )>>,
  class R = std::array<T, N>
>
R make_array( F&& f ) {
  return index_upto<N>()( [&](auto...Is)->R {
    return {{ f( Is )... }};
  } );
}

我们通过 make_array&lt;count&gt; 一个 lambda。该 lambda 从编译时 std::size_t 获取一个可转换的参数,其值为 I,并返回数组的第 I 个元素。

结果是大小为countstd::array

lambda 可以使用 auto I 来获取编译时的多汁性,或者只使用 std::size_t I 来获取值的运行时版本。

上面的大部分内容都可以翻译成 C++11,只是变得很难看。而且我不喜欢丑陋的代码。

Live example.

您的代码如下所示:

int main( void )
{
  unsigned size = 17;
  constexpr std::size_t number_objects = 3;

  auto objects = make_array<number_objects>( [&](std::size_t){ return NameClass(size); } );
}

并且objects 现在是一个 (std::) 数组 NameClass,长度为 number_objects,大小均为 size

【讨论】:

  • 很有趣,但是......在我走路的方式中,只需使用 for 循环并分配向量的每个大小,使用很少的代码并且易于理解就更容易了。 object[i].vectorName.resize( size ); 从 i = 0,到 i
【解决方案3】:

为你的类创建一个默认构造函数:

#include <vector>

class NameClass {
 public:
 NameClass() {} // default constructor

 explicit NameClass( unsigned size ){
    vectorName.resize( size );
 }
 std::vector <type> vectorName;
};

主要:

#include "lib.hpp"

int main( void )
{
  unsigned number_objects = something;
  unsigned size = other_thing;
  NameClass object[ number_objects ];

  for( unsigned i = 0; i < number_objects; i++)
    object[i].vectorName.resize( size );

  return 0;
}

示例 2 不起作用的原因是因为 C++ 没有用于创建未提供默认构造函数的对象数组的语法。

在 python 中它看起来像:

[NameClass(size) for _ in range(number_objects)]

我离题了。

要在没有默认构造函数的情况下仍然创建一个列表,你可以使用这个(问题是你为什么要这样做):

#include <iostream>

static constexpr unsigned NUM_OBJECTS = 10;
static constexpr unsigned VEC_SIZE = 30;

int main() {
    NameClass *objects = static_cast<NameClass *>(operator new [](NUM_OBJECTS * sizeof *objects));

    for (unsigned i = 0; i < NUM_OBJECTS; i++) {
        objects[i].vectorName.resize(VEC_SIZE);
    }

    // Required to free memory
    operator delete[](objects);

    return 0;
}

【讨论】:

  • 但是实现是……怎么样?你把同一个main,所以我不明白与默认构造函数有什么区别。
  • @MoisesRojo,默认构造函数允许您声明此类项目的数组。没有它,编译器就没有定义NameClass 数组的所有必要信息。我发布了一些进一步的内容来展示如何在没有默认构造函数和任何 stl 容器的情况下完成操作,但只能使用一些花哨的类 C 构造
【解决方案4】:

如果使用向量不是问题,实际上这很有效,而且非常简单。 这是一首诗……

class-test.cpp

#include <stdio.h>
#include <algorithm>

#include "class.hpp"

int main( void )
{
  std::vector <NameClass> object(number_objects, NameClass(size));

  printf("%lu\n", object[0].vectorName.size() );

  return 0;
}

class.hpp

#include <vector>
#include <algorithm>

#include <vector>

class NameClass {
 public:
 NameClass() {} // default constructor

 explicit NameClass( unsigned size ){
    vectorName.resize( size );
 }
 std::vector <double> vectorName;
};

如果你想使用数组,那么只需使用默认构造函数。

class.hpp

#include <vector>

class NameClass {
 public:
 NameClass(unsigned size) {
 vectorName.resize( size ); 
 } // default constructor

 explicit NameClass( unsigned size ){ // eliminate this
    vectorName.resize( size );
 }
 std::vector <type> vectorName;
};

class-test.cpp

#include <stdio.h>

#include "class.hpp"

int main() {
  NameClass objects[2](4);

  printf("%lu\n", objects[0].vectorName.size());

  return 0;
}

这会打印出正确的输出。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-09
    • 1970-01-01
    相关资源
    最近更新 更多