5

我意识到错误来自在自定义类中使用向量,但我一直在努力解决它们。当它是类对象的一部分时,如何调用向量方法?

这些是我得到的错误:

Word.cpp: In member function ‘void Word::addPosition(int)’:
Word.cpp:20: error: request for member ‘push_back’ in ‘((Word*)this)->Word::positions’, which is of non-class type ‘std::vector<int, std::allocator<int> >*’
Word.cpp: In member function ‘int Word::getPosition(int)’:
Word.cpp:26: error: request for member ‘size’ in ‘((Word*)this)->Word::positions’, which is of non-class type ‘std::vector<int, std::allocator<int> >*’
Word.cpp:27: error: request for member ‘size’ in ‘((Word*)this)->Word::positions’, which is of non-class type ‘std::vector<int, std::allocator<int> >*’
Word.cpp:29: error: cannot convert ‘std::vector<int, std::allocator<int> >’ to ‘int’ in return

标题

#pragma once
#include <string>
#include <vector>

class Word {
  public:
    Word();
    ~Word();
    void setWord(std::string);
    void addPosition(int);
    std::string getWord();
    int getPosition(int);
  private:
    std::string word;
    std::vector<int> *positions;
};

执行

#include "Word.h"
#include <string>
#include <vector>

Word::Word() {
    this->word = "";
    this->positions = new std::vector<int>(5);
}

void Word::setWord(std::string s) {
    this->word = s;
}

void Word::addPosition(int i) {
    this->positions.push_back(i);
}

std::string Word::getWord() {
    return this->word;
}

int Word::getPosition(int i) {
    if (i < this->positions.size() && i > 0) {
        for (int j = 0; j < this->positions.size(); i++) {
            if (i == j) {
                return positions[j];
            }
        }
    }
    return -1;
}

编辑:这是设置课程的更好方法吗?标题:

    #pragma once
    #include <string>
    #include <vector>

    class Word {
      public:
        Word();
        ~Word();
        void setWord(std::string);
        void addPosition(int);
        std::string getWord();
        int getPosition(int);
      private:
        std::string word;
        std::vector<int> positions;
    };

执行:

Word::Word(){
    word = "";
}

void Word::setWord(std::string s){
    this -> word = s;
}
void Word::addPosition(int i){
    this -> positions.push_back(i);
}
std::string Word::getWord(){
    return this -> word;
}
int Word::getPosition(int i){
    if (i < this -> positions.size() && i > 0) {
        for (int j = 0; j<this -> positions.size(); i++) {
            if (i == j) {
                return (this->positions)[j];
            }
        }
    }
    return -1;
}

但现在我收到了这个错误:

Undefined symbols for architecture x86_64:
  "_main", referenced from:
      start in crt1.10.6.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status
4

5 回答 5

9

除了@Chris 的回答,这里事实上的问题是您使用的是指向向量的指针而不是直接的向量
没有理由动态分配向量,因为它在内部使用动态内存来存储其元素。vector 的优点是它管理自己的内存,并且该内存在其范围结束时被释放:那是RAII

我个人推荐 Going Native 2013 Stroupstrup 演讲“C++ 的本质”。他提供了关于 C++ 中数据管理的漂亮示例和解释:数据与数据处理程序。

对于那些来自 Java 的人:关于 Java 和 C++ 中的内存管理的观点

在 Java 中,我们区分两种数据:基本类型(整数、字符、布尔值等)和对象(类的实例)。Java 通过垃圾收集器管理其内存:Java 运行时(JVM)分配堆上的对象使用的内存,为您提供的是指向该分配对象的指针。因此,在 Java 中,您的变量实际上是分配在堆栈上的指针,指向分配对象的堆内存(这与菜鸟使用 Java 传递值的常见问题直接相关)。这允许 Java 轻松共享对象实例的所有权:它只跟踪(通过引用计数)有多少变量引用了特定对象。
有时,垃圾收集器会查看程序堆并释放引用计数已降至零的对象(即您尚未使用的对象)使用的内存。因此,如您所见,GC 提供了一种非确定性的方式来释放/管理内存

C++ 内存管理旨在以一种确定的方式工作。所有变量都在一个特定的范围内声明,这决定了它的生命周期当一个变量的范围结束时,该变量的生命周期结束,并且在对象的情况下,它的析构函数被调用以执行适当的释放操作
这就是所谓的资源获取是初始化,或 RAII。

RAII 意味着对象管理资源(内存、文件句柄、网络端口等),该资源的获取、使用和释放与管理资源的对象的生命周期直接相关。这提供了一个确定性且无泄漏的系统来管理资源:请注意,“资源”不仅仅指内存,它是垃圾收集器管理的唯一资源。在 99% 的情况下,RAII比垃圾收集器更强大、更安全

std::vector是通过 RAII 管理资源(在这种情况下为动态分配的可调整大小的数组)的类的典型示例。
如您所见,我根本没有谈论指针:指针必须用于共享对象的所有权,或者分配内存的动态块(数组)。但请注意,第一种情况可以(并且必须)通过智能指针实现,第二种情况通过基于 RAII 的容器,例如std::vector.

使用指针动态分配 a 的问题std::vector是:

  • std::vector在内部管理一个动态数组,它在其中分配元素,因此std::vector大小(即堆栈中适合的向量)只有指向数组的指针的大小和两个计数器(整数)。不要担心堆栈中向量的大小(由于可能的堆栈溢出):数组是在堆上分配的。

  • 使用指针动态分配向量会破坏 RAII,因为向量实例的生命周期未链接到任何范围,当您决定解除分配 ( ) 向量时,它的生命周期必须由您确定。delete当然手动动态内存管理容易出错。

再次,我建议您查看 Stroupstrup 的演讲:他对此的解释比我好得多 :)

于 2013-09-14T20:54:01.897 回答
4

positions是一个指针。您需要取消引用它才能获得基向量:

this->positions->size();

通常,您遇到的错误是由于取消引用失败引起的(因为T*它不是类类型;它是指针,而指针是原始类型)。

于 2013-09-14T20:51:22.437 回答
2

positions是一个指针,所以你需要使用间接:

this->positions->push_back(i);

在这种情况下不要使用指针。您最好使用堆栈分配的向量并通过构造函数对其进行初始化:

class Word
{
    ...
private:
    std::string word;
    std::vector<int> positions;
};

Word::Word()
    : word(""), positions(5) { }

void Word::addPosition(int i)
{
    this->positions.push_back(i);
}
于 2013-09-14T20:57:28.940 回答
1

positions是一个指向向量的指针,用法应该和->操作符一起使用:

另外,请注意我改变了return positions[j];

#include "Word.h"
#include <string>
#include <vector>
Word::Word(){
    this -> word = "";
    this -> positions = new std::vector<int>(5);
}

void Word::setWord(std::string s){
    this -> word = s;
}
void Word::addPosition(int i){
    this -> positions->push_back(i);
}
std::string Word::getWord(){
    return this -> word;
}
int Word::getPosition(int i){
    if (i < this -> positions.size() && i > 0) {
        for (int j = 0; j<this -> positions->size(); i++) {
            if (i == j) {
                return (*positions)[j];
            }
        }
    }
    return -1;
}

另一种解决方案是不保存指针,像这样定义向量:

private:
    std::string word;
    std::vector<int> positions;

然后你也应该删除这条线this -> positions = new std::vector<int>(5); 你还应该知道向量在需要时会自行放大,如果它很小,你不需要指定它的初始大小(你应该考虑为非常大的值做它)

于 2013-09-14T20:53:45.510 回答
1

positions是一个指针,所以你需要positions->push_back.

另一方面,为什么要在堆上分配向量?它可以是类的成员。

于 2013-09-14T20:55:04.360 回答