【问题标题】:Pointer to const object with emplace_back指向带有 emplace_back 的 const 对象的指针
【发布时间】:2022-01-04 08:19:49
【问题描述】:

我不明白我们什么时候可以在集合中使用 const 变量/对象(尤其是 emplace)。下面的代码直接使用 const 对象,但在使用指向 const 对象的指针时不起作用。

#include <list>

class MyData {  };

int main() {
    std::list<std::pair<int, MyData>> collection1{};
    std::list<std::pair<int, MyData*>> collection2{};

    const MyData someData{};
    const MyData* someDataPtr = &someData;

    collection1.emplace_back(1, someData);
    //collection2.emplace_back(1, someDataPtr); //Messy template error!
}

我认为使用 emplace_back 而不是 push_back 作为指针并没有太大优势,但我使用 std::pair 来说明该对的另一部分可能是大/昂贵的。

具体来说,我的问题是为什么emplace_back 使用 const 对象而不使用指向 const 对象的指针?有没有合理的方法来实现后者?

对于任何想知道用例的人,我有一个成员函数,它传递对的组成部分,进行一些处理(但不应更改任何数据),然后将对放置到集合中。比如:

void add_to_schedule(const int id, const MyData* myData) {
   //some processing
   this->collection.emplace_back(id, myData);
}

【问题讨论】:

  • *collection2.front() = something; 会修改一个 const 对象,而没有人想要那样。

标签: c++ stl constants c++17 emplace


【解决方案1】:

const MyData* 无法隐式转换为 MyData*。这意味着std::pair&lt;int, MyData*&gt; 不能从{1, someDataPtr} 构造,而someDataPtrconst MyData*

在同样的逻辑下,

MyData* p = someDataPtr; // fails
MyData m = someData;     // fine

作为解决方法,您可以将someDataPtr 更改为MyData*,或将std::list 更改为std::list&lt;std::pair&lt;int, const MyData*&gt;&gt;

【讨论】:

  • 因此,制作一个 const 对象的副本很好(因为你有一个新对象,你可以用它做你想做的事)。复制一个指向 const 对象的指针不是(没有新对象,只是原始 const 对象的新句柄,所以还是不能修改)?
  • @Verwirrt 你是对的。使复制成为可能意味着原始对象可能会通过新指针被修改,这是不期望的。
  • @Verwirt 从技术上讲有一个新对象,指针就是一个对象。你是对的,没有另一个 MyData 对象
猜你喜欢
  • 1970-01-01
  • 2014-10-28
  • 2010-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-07
  • 1970-01-01
相关资源
最近更新 更多