【问题标题】:Why vectors inside two struct have the same address?为什么两个结构内的向量具有相同的地址?
【发布时间】:2020-06-03 20:49:23
【问题描述】:

为了避免重复代码,我想构建这个通用结构。我希望 scaledown24 结构内的 numbers24 向量与 scaledown32 结构内的 numbers32 向量不同。所以当我做出改变时,他们将无法相互影响。但是当我运行程序时, printAddress 函数显示两个向量的地址是相同的。我怎样才能解决这个问题。谢谢。

#include <iostream>
#include <vector>

struct ScaleDown24{
    static std::vector<int> getVector() {
        std::vector<int> numbers24(3);
        return numbers24;
    };
    static inline void printAddress(std::vector<int>sumNumbers ) {
        std::vector<int> *p = &sumNumbers;
        std::cout << p << "\n";
    }
};

struct ScaleDown32{
    static std::vector<int> getVector() {
        std::vector<int> numbers32(4);
        return numbers32;
    };
    static inline void printAddress(std::vector<int>sumNumbers ) {
        std::vector<int> *p = &sumNumbers;
        std::cout << p << "\n";
    }
};

template<typename ScaleFunction>
void scaleDown(){
    std::vector<int>sumNumbers = ScaleFunction::getVector();
    ScaleFunction::printAddress(sumNumbers);

}

int main()
{
    scaleDown<ScaleDown24>();
    scaleDown<ScaleDown32>();
    return 0;
}

【问题讨论】:

    标签: c++


    【解决方案1】:

    您的printAddress() 函数采用按值 的参数。这意味着您正在复制您传递给它的任何vector,而您正在打印的地址就是该副本。

    您需要做的是通过引用传递向量参数,这样您就可以获得原始地址,而不是副本。看起来像这样:

    static inline void printAddress(std::vector<int>& sumNumbers )
    //                         this means reference ^       
    

    scaleDown() 也会有问题:

    template<typename ScaleFunction>
    void scaleDown(){
        std::vector<int>sumNumbers = ScaleFunction::getVector();
        ScaleFunction::printAddress(sumNumbers);
    
    }
    

    因为sumNumbers 是一个非静态局部变量,因此每次调用该函数时它都可以具有相同的地址。如果您只想让每个 ScaleFunction 拥有自己的向量,您可以将其设为 `static 以执行此操作:

    template<typename ScaleFunction>
    void scaleDown(){
        static std::vector<int>sumNumbers = ScaleFunction::getVector();
        ScaleFunction::printAddress(sumNumbers);
    
    }
    

    还请注意,由于printAddress() 不会修改向量,并且您不希望它这样做,因此您可以创建向量const 来帮助执行该操作。那会给你这个:

    static inline void printAddress(const std::vector<int>& sumNumbers ) {
        // no need for the pointer here
        std::cout << &sumNumbers << "\n";
    }
    

    【讨论】:

    • 这只是问题的一半。在scaleDown 中,sumNumbers 是本地的。它可能 (and indeed does) 在两次调用中都出现在同一位置。
    • printAddress() 应该通过const 引用来获取其参数,因为它不会修改参数:static inline void printAddress(const std::vector&lt;int&gt;&amp; sumNumbers )
    • @RemyLebeau 好点,我已将其添加到答案中。另外,感谢您的编辑
    • @PaulSanders 好地方。我已经为此添加了一个潜在的修复方法
    • 感谢您的回答。雷米的回答是正确的。
    【解决方案2】:

    您的代码存在几个问题。主要是因为getVector() 方法都按值返回它们的向量,并且printAddress() 方法也都采用按值的参数。因此,您正在到处处理副本的向量。您会看到内存在不同的上下文中得到重用。

    您需要在代码中引入一些引用以避免这些副本,例如:

    #include <iostream>
    #include <vector>
    
    struct ScaleDown24{
        static std::vector<int>& getVector() { // <-- return a reference
            static std::vector<int> numbers24(3); // <-- make static to avoid returning a reference to a local variable
            return numbers24;
        };
        static inline void printAddress(const std::vector<int> &sumNumbers ) { // <-- take a const reference
            const std::vector<int> *p = &sumNumbers;
            std::cout << p << "\n";
        }
    };
    
    struct ScaleDown32{
        static std::vector<int>& getVector() { // <-- return a reference
            static std::vector<int> numbers32(4); // <-- make static to avoid returning a reference to a local variable
            return numbers32;
        };
        static inline void printAddress(const std::vector<int> &sumNumbers) { // <-- take a const reference
            const std::vector<int> *p = &sumNumbers;
            std::cout << p << "\n";
        }
    };
    
    template<typename ScaleFunction>
    void scaleDown(){
        std::vector<int> &sumNumbers = ScaleFunction::getVector(); // <-- save a reference, not a local copy
        ScaleFunction::printAddress(sumNumbers); // <-- prints the original vector that is inside getVector()!
    }
    
    int main()
    {
        scaleDown<ScaleDown24>();
        scaleDown<ScaleDown32>();
        return 0;
    }
    

    Live Demo

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-04-05
      • 2022-11-23
      • 2023-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多