【问题标题】:Class type for stack allocation. Why the address for both ID instances are the same?堆栈分配的类类型。为什么两个 ID 实例的地址相同?
【发布时间】:2020-09-24 21:10:33
【问题描述】:
class ID
{
public:
    ID(const std::string& name) :
        name_(name) {}

    // explicit copy constructor as my first solution but gave me same address
    ID(const ID& other)
    { name_ = other.getName(); } 

    std::string getName() const
    { return name_; }

private:
    std::string name_;
};

ID createID(const std::string& name)
{
    ID id(name); // new stack allocation for id
    std::cout << "ID addr: " << &id << "\n";
    return id;
}

int main()
{
    ID my_id = createID("John"); // new stack allocation for my_id
    std::cout << "my_id addr: " << &my_id << "\n";
    std::cout << my_id.getName() << std::endl;
}

平台:Ubuntu 终端(Windows 的 Ubuntu 子系统)

编译:g++ file.cpp

输出:“ID 之间的地址相同”

不应该输出提供不同的堆栈地址吗?

我尝试用原始整数(而不是 ID 类类型)复制它,它为不同的实例输出不同的地址。

int func(int i)
{
        int j = i;
        std::cout << "i addr: " << &i << std::endl;
        std::cout << "j addr: " << &j << std::endl;
        return i;
}

int main()
{
        int x = 10;

        std::cout << "X addr: " << &x << std::endl;
        int y = func(x);
        std::cout << "Y addr: " << &y << std::endl;
}

【问题讨论】:

  • 请显示您正在运行的完整示例。在您的代码中,我没有看到“ID 之间的地址相同”。
  • 类从第一个变量的开头开始。如果它是继承类,则从父类的第一个变量开始。如果它有虚函数,那么它以虚表的地址开始。所以第一个变量地址和类的地址是一样的。如果类中有更多变量,则每个新变量都放在前一个变量之后。
  • 这就是所谓的命名返回值优化NRVO。看来我们只有解释 RVO 和复制 ellison 的副本 - What are copy elision and return value optimization?

标签: c++ memory-management stack-allocation


【解决方案1】:

在这个函数中:

ID createID(const std::string& name)
{
    ID id(name); // new stack allocation for id
    std::cout << "ID addr: " << &id << "\n";
    return id;
}

来电:

ID my_id = createID("John"); // new stack allocation for my_id

看来编译器正在执行NRVO(命名为返回值优化)。所以函数中没有id的实际副本到变量my_id,也没有单独分配。

取而代之的是,此副本被省略了,您会看到相同的地址。所以// new stack allocation for my_id这个评论其实是不正确的。

请注意,NRVO 不一定会发生,因此您不应依赖此行为。编译器可以进行复制,从而产生不同的地址。事实上,这就是func 返回int 的示例中发生的情况。由于这是一种廉价的复制类型,因此编译器实际上会进行复制,并且您会看到不同的地址。

【讨论】:

  • @cmasterisk 没问题。另请查看对您的问题的评论中提供的链接。那里有很多有用的信息。另外,如果 accepting 回答了您的问题,请考虑答案。
猜你喜欢
  • 2019-09-14
  • 1970-01-01
  • 1970-01-01
  • 2017-11-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-01
  • 1970-01-01
相关资源
最近更新 更多