c++数组问题
Posted
技术标签:
【中文标题】c++数组问题【英文标题】:c++ array question 【发布时间】:2010-07-14 06:09:33 【问题描述】:我想初始化一个大小为 200 的双精度数组,它的值是 c++ 中索引 0 到 199 的 0 到 199。 我知道我可以通过一个简单的 For 循环来做到这一点,但是有没有办法像这样初始化双精度数组?
谢谢
【问题讨论】:
见How to fill a vector with non-trivial initial values?。其他几个选项包括 iota(非标准)和 Boost 的 counting_iterator。 @Matthew:哇,我从来不知道counting_iterator
。您应该将其添加为答案,否则我将窃取它。 :)
【参考方案1】:
不是真的。 for 循环是您的最佳选择:
double array[200];
for(int i = 0; i < 200; i++)
array[i] = static_cast<double>(i);
【讨论】:
这是唯一的答案,我想。即使是 c++ 新手也会毫不费力地理解它。其他答案(std::generate、counting_iterator 等等)是为了展示 c++ 的技巧,而不是解决实际问题。代码应该尽可能简单(但不是更简单)=) @Sad:counting_iterator
的解决方案很简单。
@Sad:这样的项目很糟糕。标准库是语言的一部分;使用失败表示程序员在 C++ 中编程失败。应该在允许的情况下使用 Boost,尽管这对某些人来说并不总是可行的。 (再说一遍,您可以轻松提取单个库。)对std::copy
缺乏了解是无法判断C++ 代码,因为一个人不是C++ 程序员。
@SadSido:在一定程度上我同意 GMan。每个程序员都需要一个经过调试的高性能库来进行基本操作。不管那个图书馆实际上是什么。例如,EA Games 使用 EASTL,它使用专用分配器以及分配和初始化策略来实现更高的性能。但我想说没关系:我希望任何 C++ 程序员都能够在互联网上搜索并了解当我使用一些 STL 或 Boost 部件时发生了什么,就像这里提到的那样简单(我不是在说boost::mpl
)。
@SadSido:你可能不喜欢它,但 GMan 是对的。 C++ 是语言加上标准库,并且非常强调后者。使用循环的甚至不到六个答案中的一个一开始就出错了循环,这说明了为什么循环并不优越。【参考方案2】:
这是std::generate
的一种方式:
template <typename T>
class nexter
public:
nexter(T start = T())
: value_(start)
T operator()()
return value_++;
private:
T value_;
;
int main()
double data[200];
std::generate(data, data + 200, nexter<double>());
如果你使用的是 C++0x,你可以跳过仿函数:
int main()
double data[200];
double next = 0.0;
std::generate(data, data + 200, [&next]() return next++; );
【讨论】:
严格来说,我认为for_each
实际上并不打算改变元素。此外,如果您想忽略一个参数,请不要命名它。最后,如果您要使用仿函数,不妨使用std::generate
。 :)
@GMan - 谢谢,我忘记了 std::generate
- 更新了我的示例,还给出了一个使用 C++0x lambdas 的示例。
@RSamuel:+1 很好,C++0x 解决方案可以说是迄今为止最干净的。 (如果只有标准库使用该死的范围而不是迭代器!)为了记录,-1 不是我。
@GMan - 谢谢。而且我等不及 lambda 不被认为是最先进的,因为它们非常好用。
+1 但只是为了展示一个不错的 C++0x lambda。函子版本是...不,请。不要那样做。【参考方案3】:
使用counting_iterator
:
const int SIZE = 200;
double array[SIZE];
std::copy(counting_iterator<int>(0), counting_iterator<int>(SIZE), array);
【讨论】:
恕我直言,::std:;copy
应该被编写为要求目标开始和结束,源开始而不是相反。无论哪种方式,您都可以获得缓冲区溢出,但当溢出只是读取而不是写入时,更难利用。
@Omnifarious:更好的是,两者都需要;)但我同意阅读溢出不太可能导致问题。
像 GMan 我不知道这个小奇迹。如此简单实用!【参考方案4】:
与anthony-arnold 相同,但使用 C++ 向量(或列表或双端队列):
std::vector<double> array ;
array.reserve(200) ; // only for vectors, if you want
// to avoid reallocations
for(int i = 0; i < 200; i++)
array.push_back(i) ;
【讨论】:
【参考方案5】:如果数组的所有值都相同,则可以轻松完成。但是价值观是不同的,所以我不认为你直接这样做。
double array[200];
for(int i=0 ; i<200 ; i++)
array[i] = (double)i;
【讨论】:
您的代码在i = 200
时会导致无效的内存访问,因为它将写入array[200]
。将array[i]
的赋值放到它所属的for
语句的主体中!
哦,此外,array[0]
没有写入并且保持未初始化状态。
我不认为 c++ 的机制如何。如果它从左侧解析句子,则没有任何无效的内存访问。 for 循环结束,直到“array[i] = (double)i”
对不起。我认为它在执行 "i++ , array[i] = (double)i" 之后检查条件。我想它会在 i++ 和条件等每个操作之后检查。
@Judas:不,它会在分配后进行检查。【参考方案6】:
如果200
是一个固定常量并且您不想要运行时开销,我基本上看到了两种解决方案。
对于 C 解决方案,您可以通过预处理器解决它。在认为 Boost 有预处理器 for
循环这样的事情。这样做的好处是可以在编译时完成,完全没有运行时开销。
对于所有编译器/预处理器来说,常量 200 本身可能有点大,但大多数现代编译器/预处理器应该能够处理这个问题。
我认为,对于 C++ 解决方案,您可以使用 template
元编程来实现。具有template
参数中元素数量的递归类型可以解决问题。但是对于这么大的常量,编译时间开销可能会令人望而却步。
【讨论】:
有趣的选项,但没有一个比循环更容易被调用。尤其是模板递归是一个很难理解的东西 @Elemental:取决于对谁来说更简单。如果你有一个通用的宏来做这件事,那么调用端就会变得非常简单,比如double A[] = INIT_DARRAY(200);
。当然,这样一个宏的实现并不简单,但这确实是硬币的另一面。并且这样的宏是否隐藏了真正的宏定义 à la Boost 或递归模板在这方面并不重要。【参考方案7】:
初始化数组值的唯一方法是在声明点(如果初始化器小于数组,则所有其他元素都初始化为零;
double arr[5] = 0, 1, 2; // arr = [0.0 ,1.0 ,2.0 ,0.0 ,0.0]
否则无法初始化值,您将不得不遍历数组。
所以你可以做的是:
double arr[] = 0, 1, 2, 3, /* ... */, 199;
虽然循环会更好在大多数情况下。
【讨论】:
与循环表示法相比,另一个优点是可以在编译时解决。缺点是写起来很痛苦...... @paercebel,当然,它是在编译时完成的,这是 only 的优势。至于写它,我会用脚本生成一次,以免出错。【参考方案8】:我认为 for-loop 是最适合您的情况的最简单和最合适的解决方案。如果您只想知道另一种方法,可以使用std::transform
:
#include <vector>
#include <algorithm>
double op_increase (double i) return static_cast<double>(static_cast<int>(i)+1);
int main()
std::vector<double> x( 200 ); // all elements were initialized to 0.0 here
std::transform( x.begin(), x.end()-1, x.begin()+1, op_increase );
return 0;
【讨论】:
以上是关于c++数组问题的主要内容,如果未能解决你的问题,请参考以下文章