定义一个生成元素向量的函数时,正确的方法是什么?

What is the correct approach while defining a function that generates a vector of elements C++

本文关键字:函数 是什么 方法 向量 一个 元素 定义      更新时间:2023-10-16

我必须在c++中定义一个函数来生成类Foo的向量并返回它。

我可以用不同的方式来定义它,它们都是等价的:

C风格参数传递:

void generateFooVector(vector<Foo> * result)
{
    for (int i = 0; i < 100; i++)
    {
        Foo f = Foo();
        result->push_back(f);
    }
}
int main()
{
    vector<Foo> result;
    generateFooVector(&result);
}

引用传递:

void generateFooVector(vector<Foo> & result)
{
    for (int i = 0; i < 100; i++)
    {
        Foo f = Foo();
        result->push_back(f);
    }
}
int main()
{
    vector<Foo> result;
    generateFooVector(result);
}

实例化vector并返回指针:

vector<Foo> * generateFooVector()
{
    vector<Foo> * result = new vector<Foo>();
    for (int i = 0; i < 100; i++)
    {
        Foo f = Foo();
        result->push_back(f);
    }
    return result;
}
int main()
{
    vector<Foo> * result = generateFooVector();
}

C风格传递和实例化Foo类:

void generateFooVector(vector<Foo *> * result)
{
    for (int i = 0; i < 100; i++)
    {
        Foo * f = new Foo();
        result->push_back(f);
    }
}
int main()
{
    vector<Foo *> result;
    generateFooVector(&result);
}

引用传递+ Foo实例:

void generateFooVector(vector<Foo *> & result)
{
    for (int i = 0; i < 100; i++)
    {
        Foo * f = new Foo();
        result->push_back(f);
    }
}
int main()
{
    vector<Foo *> result;
    generateFooVector(result);
}

Vector实例+ Foo实例:

vector<Foo*> * generateFooVector()
{
    vector<Foo*> * result = new vector<Foo*>();
    for (int i = 0; i < 100; i++)
    {
        Foo * f = new Foo();
        result->push_back(f);
    }
    return result;
}
int main()
{
    vector<Foo *> * result = generateFooVector();
}

按值传递:

vector<Foo> generateFooVector()
{
    vector<Foo> result;
    for (int i = 0; i < 100; i++)
    {
        Foo f = Foo();
        result->push_back(f);
    }
    return result;
}
int main()
{
    vector<Foo > result = generateFooVector();
}

也许还有很多其他的解决方案。

当前所有的方法对于如何在作用域内分配内存都有不同的含义。

也许我缺乏理论,但我真的很困惑,我如何才能决定哪个是每个用例的更好的替代方案,为什么一个比另一个更好。你能帮我吗?

只管做

vector<Foo> generateFooVector()
{
    return vector<Foo>(100);
}

它叫做modern c++

该函数已在标准库中定义,称为std::vector<Foo>的构造函数。你可以把它命名为(c++ 11风格)

auto v = std::vector<Foo>(n); // create n default constructed Foo() objects

或c++ 98风格的

(在c++ 11中也有效)
std::vector<Foo> v(n); 

我不会尝试包装这个

    首先,你不想在
  • 中隐藏像100这样的幻数,而不是在参数列表(模板或运行时)中。
  • 不包装构造函数的另一个原因是为了避免读者产生混淆。如果我遇到一个generateVector函数,第一个问题是:"与普通构造函数调用相比,这个函数是否做了其他/额外的事情?"

我确实看到了两个主要不同的实现- vector<Foo*>vector<Foo>。其他都是参数传递的变体。

如你所知,vector在添加时复制元素,在删除vector时调用元素析构函数。所以在vector<Foo*>的情况下,你避免了对象的复制,如果对象非常大的话。但是你负责删除内存。所以最好存储带有自动删除功能的智能指针,比如vector<shared_ptr<Foo>>vector<unique_ptr<Foo>>(这里需要移动逻辑)。指针的类型取决于应用程序的逻辑。

顺便说一句,

 Foo* pFoo = new Foo;  // also default constructor call

(你知道与new Foo()的区别吗?)

 vector<Foo> v(n);  // init vector with n Foo objects calling default ctor 

我可能会采用上面的引用传递方法。

通常在C和c++中,您不希望返回需要稍后重新分配的对象,因为这会导致泄漏。

我认为这很大程度上取决于实际使用情况——最关键的是foo有多重?如果foo是一个轻量级对象并且是类似pod的类型,那么我将使用

Vector<Foo> generateFoo();

或者像

Vector<Foo*> generateFoo();

可能更有用。

标准类型是有效的,大多数喜欢被复制,所以它们对向量*解决方案没有什么优势。一般来说,返回(或使用)一个需要稍后删除的原始指针可能是不明智的——在这种体系结构中很容易产生泄漏。所以,不妨看看foo对象的各种智能指针选项。