【问题标题】:Why does push_back fail for unique_ptr of string vectors?为什么字符串向量的 unique_ptr 的 push_back 失败?
【发布时间】:2021-06-23 21:51:26
【问题描述】:

以下代码存在分段错误。当不涉及 unique_ptr 时,一切正常。

#include <iostream>

int main() {
  auto vect = std::unique_ptr<std::vector<std::string>>();

  vect->push_back("abc");  // Segmentation Fault.
  vect->emplace_back("abc");  // Segmentation Fault.

  return 0;
}

如果遇到这种情况,我在 Ubunutu 上使用 g++ 10.2 进行编译。

【问题讨论】:

  • 你创建了一个empty unique_ptr! (行尾的 ()unique_ptr` 的默认构造函数 - 不是保持向量的构造函数。)将一些东西 放入 它,例如,一个空的向量(来自堆)。 (“空”表示空:它没有指向任何东西。)
  • 你为什么要首先在堆上创建std::vector(或std::string)?
  • 好吧,@gph,如果 C++ 编译器在 C++ 程序员遗漏了一些明显的事情时发出警告 - 好吧,它肯定会让 C++ 编译器编写者忙于思考它们!有很多简单的方法可以让自己上吊(还有更困难的方法......)......这就是为什么它是如此有趣和令人兴奋的语言!

标签: c++ c++11 unique-ptr


【解决方案1】:

您需要按如下方式初始化您的unique_ptr 实例:

using type = std::vector<std::string>;
auto vect = std::make_unique<type>();

vect->push_back("abc");     // No segfaults now
vect->emplace_back("abc");  // No segfaults now either

std::cout << vect->at(0) << std::endl;

【讨论】:

    【解决方案2】:

    您已经使用其默认构造函数声明了一个std::unique_ptr,因此它持有一个nullptr 指针。您没有创建一个 std::vector 对象来指向它。

    使用new 创建std::vector

    int main() {
        auto vect = std::unique<std::vector<std::string>>(new std::vector<std::string>);
        // or:
        // std::unique<std::vector<std::string>> vect(new std::vector<std::string>);
        vect->push_back("abc");
        vect->emplace_back("abc");
        return 0;
    }
    

    或者,在 C++14 及更高版本中,使用 std::make_unique() 而不是手动构造 std::vector

    int main() {
        auto vect = std::make_unique<std::vector<std::string>>();
        vect->push_back("abc");
        vect->emplace_back("abc");
        return 0;
    }
    

    但是你真的不应该在动态内存中创建标准容器,除非你绝对需要。

    int main() {
        std::vector<std::string>> vect;
        vect.push_back("abc");
        vect.emplace_back("abc");
        return 0;
    }
    

    【讨论】:

    • 堆上的标准容器,该函数正在解析具有未知数量元素的文件(在这种情况下为字符串,但并非总是如此)。尽管我如何展示示例(总傻瓜时刻),但我正在使用 make_unique。我不是动态向量分配的粉丝,但我不确定如何构造 unique_ptr。对想法完全开放!
    • @gph "该函数正在解析具有未知数量元素的文件" - 不需要将向量本身分配到堆上,如下所示我的第三个例子。
    • 对,向量正在传回给调用者。我又看了看,如果我按价值返回,它会被感动所以是的,这似乎很好。
    • @gph 是的,您不需要动态分配向量,而是使用移动语义。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-02-16
    • 1970-01-01
    • 2011-04-04
    • 1970-01-01
    • 1970-01-01
    • 2019-12-25
    • 1970-01-01
    相关资源
    最近更新 更多