如何建立一个全球性的容器(C ++ 03)?(How to setup a global conta

2019-08-04 04:41发布

我想定义一个全局容器(C ++ 03),这里是一个示例代码,我想,这是行不通的。

#include <vector>
#include <string>
using namespace std;

vector<string> Aries;
Aries.push_back("Taurus");    // line 6

int main() {}

编译错误:

prog.cpp:6:1: error: 'Aries' does not name a type

看来我可以定义一个空的全球性载体,但无法填满它。 看起来像在C ++ 03,我也不能指定一个初始值设定,如:

vector<string> Aries = { "Taurus" };

有我在这里犯了一个错误,或者我该如何解决这个问题?

我试图寻找在计算器上,看看是否已经回答过了,但只有在这些帖子就来了: 在C ++全局对象 , 在C ++中定义全局常量 ,这并没有帮助回答这个问题。

Answer 1:

当某项功能(如外部声明和初始化main )没有问题,你不能有功能之外的代码。 你要么需要设置正确的初始化值(如C ++ 11),或填写您的全局对象在主:

std::vector<string> Aries;

/* ... */

int main() {
    Aries.push_back("Taurus");
    /* ... */
}

其他方式(不填充在主载体)

单值

有哪些不需要其他方式.push_back在主或其他代码。 例如,如果Aries应包含仅一个项目时,可以使用std::vector<T>::vector(size_t s, T t)s == 1t == "Taurus"

std::vector<string> Aries(1, "Taurus");

/* ... */

int main() { /* ... */ }

如果您需要在同一价值数时间,你可以简单地调整s

多个不同的价值

现在这样会稍微有点麻烦。 要填充的vector使用合适的构造。 std::vector<T>提供了在C ++ 03四种不同的构造函数:

  1. std::vector<T>::vector()
  2. std::vector<T>::vector(size_t, T = T())
  3. template <class InputIt> std::vector<T>::vector(InputIt, InputIt)
  4. std::vector<T>::vector(const vector&)请注意,所有的人都采取实际的分配额外的最后一个参数,但是这是我们关心的问题。

我们可以忘掉std::vector<T>::vector()因为我们要填充值的向量,并且还std::vector<T>::vector(size_t, T)不适合,因为我们希望不同的值。 剩下的就是模板化构造函数和拷贝构造函数。 下面的示例演示了如何使用模板的构造函数:

std::string const values[] = {"Taurus", "Ares", "Testos"};

template <class T, size_t N>
T* begin(T (&array)[N]){ // this is already in C++11, very helpful 
    return array;
}
template <class T, size_t N>
T* end(T (&array)[N]){
    return array+N;
}

std::vector<std::string> Aries(begin(values), end(values));

请注意, beginend是没有必要的-我们可以简单的使用Aries(values, values+3) 然而,事情往往会发生变化,而且往往你添加一个值,或者删除一个。 如果您忘记更改偏移3 ,你要么忘记的条目或跨越边界values

然而,这种解决方案引入了一个新的全局变量,这是不是很好。 让我们退后一步。 我们需要values ,因为我们想用std::vector<T>::vector(InputIt, InputIt)它需要一个有效的范围内。 并且范围必须在我们使用构造的时间是已知的,所以它必须是全球性的。 诅咒! 但是你看:我们的工具箱中还包含一个构造函数,拷贝构造函数。 为了使用它,我们创建一个额外的功能:

namespace {
    std::vector<std::string> initializer(){
        const std::string dummy_array[] = {"Taurus", "Ares", "Testos"};
        return std::vector<std::string>(begin(dummy_array), end(dummy_array));
    }
}

std::vector<std::string> Aries(initializer());

这个例子同时使用拷贝构造函数和范围的构造。 您还可以创建一个临时的载体和使用std::vector<T>::push_back来填充它的功能。



Answer 2:

我发现了一个整洁的解决办法,以“初始化” C ++ 03全球STL容器(实际上之前执行代码“全球” main() 这将使用逗号操作符。 见例如:

#include <vector>
#include <string>
#include <iostream>
using namespace std;

vector<string> Aries;

// dummy variable initialization to setup the vector.
// using comma operator here to cause code execution in global scope.
int dummy = (Aries.push_back("Taurus"), Aries.push_back("Leo"), 0);

int main() {
    cout << Aries.at(0) << endl;
    cout << Aries.at(1) << endl;
}

产量

Taurus
Leo

唯一真正的问题,如果你能叫的,是额外的全局变量。



Answer 3:

我的经验是,这个“惊人的,但可怕的”(帽尖)解决方案是不可预测的。 你的初始化加载时运行。 你有没有保证,以加载顺序。 因此,使用该集装箱一切都必须在同一个模块无论是在,或以某种方式保证他们进入容器之前的模块被加载。 否则,容器构造还没有运行,但你的代码调用愉快它的存取。

当它出现问题,它会非常错误的,错误是编译器,平台,月亮依赖的阶段 - 在所有情况下不给予最偏远的线索,以什么去了南方。



Answer 4:

而就的完整性,该解决方案使用迭代器对构造和朴实的数组初始化。

#include <vector>
#include <string>
#include <iostream>
using namespace std;

string contents[] = {"Taurus", "Leo"};
vector<string> Aries(contents, contents + sizeof contents/sizeof contents[0]);

int main() {
    cout << Aries.at(0) << endl;
    cout << Aries.at(1) << endl;
}

这可能是更清晰,但它调用更多的拷贝构造函数。



文章来源: How to setup a global container (C++03)?