【问题标题】:Should I always deal with reference returning vector?我应该总是处理参考返回向量吗?
【发布时间】:2017-02-21 13:34:15
【问题描述】:

不确定here 发生了什么:

#include <iostream>
#include <vector>

class Voice
{
public:
    double mValue = 0.0;

    Voice() { }
    Voice(const Voice &copy) {
    }    
};

class VoiceManager
{
public:
    std::vector<Voice> mVoices;

    VoiceManager() {
        mVoices = std::vector<Voice>(numVoices, Voice());   

        for (int i = 0; i < numVoices; i++) {
            mVoices[i].mValue = 100.0;
        }        
    }

private:
    int numVoices = 16;    
};

int main()
{    
    VoiceManager voiceManager;
    Voice voice = voiceManager.mVoices[2];
    std::cout << voice.mValue << std::endl;
}

我为每个Voice 设置了mValue,其值为100,运算符为[],但是当我尝试使用相同的[] 运算符检索对象时,它似乎返回的不是那个元素?它打印 0。

相反,如果我这样做:

Voice &voice = voiceManager.mVoices[2];

我终于可以看到更新的值了。

这里发生了什么?

【问题讨论】:

  • Voice::Voice(Voice const&amp;) 是做什么的?
  • 你的复制构造函数做错了;我怀疑修复它会解决你的问题。您可以省略它并回退到隐式生成的那个;或者mValue = copy.mValue;
  • 您的复制构造函数实际上并没有制作副本。只需摆脱它并使用编译器提供的那个。

标签: c++ vector reference stl


【解决方案1】:

如 cmets 所示,您的复制构造函数 a) 错误 b) 多余

class Voice
{
public:
    double mValue = 0.0;

    // don't provide default constructor, unless you have another constructor
    // use compiler-generated copy-constructor
};

class VoiceManager
{
    int numVoices = 16;    // move up here so that member-initialization works
public:
    std::vector<Voice> mVoices;

    VoiceManager() 
    :
        mVoices(numVoices) // member-initialize
    {
        for (int i = 0; i < numVoices; i++) {
            mVoices[i].mValue = 100.0;
        }        
    }
};

int main()
{    
    VoiceManager voiceManager;
    Voice voice = voiceManager.mVoices[2];
    std::cout << voice.mValue << std::endl;
}

Live Example

请注意,我还使用成员初始化语法对 VoiceManager 的构造函数进行了小幅清理。

至于另一个问题:初始化

Voice voice = voicemanager.mVoice[2]; 

实际上调用了你的复制构造函数

Voice(voicemanager.mVoice[2]);

(这里的= 符号并不意味着赋值!)

【讨论】:

  • 但我问为什么 :) 为什么如果我使用 mVoices[i].mValue = 100.0; 它将值设置为“副本”,而 Voice voice = voiceManager.mVoices[2]; 不返回“副本”实例?
  • @paizza 你的拷贝构造函数是空的
  • 我明白了 :) 但我没有在那里设置 mValue。我在这里设置mVoices[i].mValue = 100.0;。所以无论我在哪里设置该值,当我返回相同的声音(即Voice voice = voiceManager.mVoices[2];)时,我应该会看到设置值。没有?
  • @paizza Voice voice = voiceManager.mVoices[2]; 实际上调用了Voice(voiceManager.mVoices[2]),即复制构造函数,而那是空的。请注意,复制初始化(使用=)与赋值不同!
  • @paizza 是的,真的。 Voice v; v = voicemanager.mVoices[2];(默认构造+赋值)和Voice v = voicemanager.mVoices[2];(复制初始化)是有区别的。这就是存在 3 规则的原因:如果您覆盖任何复制构造函数、复制赋值或析构函数,则将它们全部覆盖并使其保持一致
猜你喜欢
  • 2020-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-01
  • 2019-10-13
  • 2016-09-05
  • 2018-10-13
相关资源
最近更新 更多