小编m8m*_*ble的帖子

复制Elision为返回的Temporaries

我试图理解C++ 17标准保证的生命周期,特别是对于保证的复制精度.让我们从一个例子开始吧

std::string make_tmp();

std::string foo() {
   return std::string{make_tmp().c_str()};
}
Run Code Online (Sandbox Code Playgroud)

我不知道发生了什么: make_tmp创造一个临时的string我们会打电话t; foo返回(不必要创建)临时(副本tc_str).标准(甚至是前C++ 17)保证了生命周期t是评估完整返回表达式之前的时间.因此它是安全的,所以创建t(要返回)的临时副本.

现在复制分支开始了; 更具体地说,第一个C++ 17块中的第二个项目:

在函数调用中,如果return语句的操作数是prvalue,并且函数的返回类型与该prvalue的类型相同.

因此,甚至根本不会创建临时副本.

后续问题:

  1. 返回的临时副本是否仍然意味着足够延长的寿命t- 即使保证被省略?

  2. 考虑foo下面给出的变体.我假设,不再需要复制省略(但很可能).如果副本不会被删除,那么标准就会被我们覆盖(通过上面的论点).如果副本被省略,t尽管returned-expression foo的类型与返回类型不同,标准是否仍能保证足够的生命周期?

foo-Variant:

std::string foo() {
   return make_tmp().c_str();
}
Run Code Online (Sandbox Code Playgroud)

我想了解标准纯粹暗示的保证.请注意,我知道两个foo版本都"工作" 的事实(即即使在各种编译器下使用自定义类进行测试时也没有涉及悬空指针).

c++ standards c++17

8
推荐指数
2
解决办法
235
查看次数

从ArgumentParser获取允许参数的正确方法

问题:从现有argparse.ArgumentParser对象访问可能的参数的预期/官方方式是什么?

示例:我们假设以下上下文:

import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--foo', '-f', type=str)
Run Code Online (Sandbox Code Playgroud)

在这里,我想获得以下允许参数列表:

['-h', '--foo', '--help', '-f']
Run Code Online (Sandbox Code Playgroud)

我找到了以下解决方法,它为我提供了诀窍

parser._option_string_actions.keys()
Run Code Online (Sandbox Code Playgroud)

但我对此并不满意,因为它涉及访问_未正式记录的成员.什么是这项任务的正确选择?

python argparse

7
推荐指数
1
解决办法
339
查看次数

std::unordered_set 迭代器遍历的复杂性

我最近玩了一个std::unordered_set. 我怀疑我的 STL 版本会跟踪某些 FILO 数据结构(看起来像列表)中的非空存储桶。我想这样做是为了提供O(n)完整的时间遍历std::unordered_set(其中表示 a 中带有桶且远大于n的元素数量)。这改进了及时遍历所有桶的方式。unordered_setmmnO(m)

我已经测试过,确实遍历大型且非常稀疏的unordered_sets (带有begin- end)比简单遍历所有存储桶要快得多。

问题:这个遍历运行时间是由标准保证的吗?或者这只是我特定标准库的一个功能?


这是我可以使用的测试代码:

#include <iostream>
#include <vector>
#include <numeric>
#include <unordered_set>
using namespace std;

void test(vector<int> data, int alloc_size) {
   unordered_set<int> set(alloc_size);
   for (auto i: data) {
      set.insert(i);
   }

   for (size_t bidx = 0; bidx < set.bucket_count(); ++bidx) {
      cout << "[B" << bidx << ":";
      for (auto bit = set.begin(bidx); …
Run Code Online (Sandbox Code Playgroud)

c++ stl std c++11

7
推荐指数
1
解决办法
3313
查看次数

删除 lambda 赋值运算符背后的基本原理?

我刚刚了解到 C++ 中的(偶数mutable)lambda 是不可赋值的,除非它有空捕获(cf ClosureType::operator=)。

例子:

auto x = 0;
auto l0 = [copy = x]() mutable {};
auto l1 = []() mutable {};

static_assert(not std::is_copy_assignable_v<decltype(l0)>);
static_assert(std::is_copy_assignable_v<decltype(std::ref(x))>);
static_assert(std::is_copy_assignable_v<decltype(l1)>);
Run Code Online (Sandbox Code Playgroud)

我想问一下这个选择背后的理由:为什么被operator=删除?特别是在可以默认的情况下,即 lambda 是mutable并且所有捕获本身都是可复制分配的(例如l0在上面的示例中)?

我知道非 lambda 的相关问题mutable。但我想理解这个决定,而不是绕过它。

c++ lambda

5
推荐指数
1
解决办法
147
查看次数

删除元素后,std :: string容量保持不变,那么它是否会占用一些内存?

以下代码:

string a = "abc";
cout << a.capacity();
a.erase(a.begin() + 1, a.end());
cout << a.capacity();
Run Code Online (Sandbox Code Playgroud)

...输出:

33
Run Code Online (Sandbox Code Playgroud)

即使我从字符串中删除了一些元素,容量也保持不变.所以我的问题是:

  1. 由于容量,一些内存是否被阻止?如果我没有明确表示reserve()怎么办?

  2. 如果我使用reserve()并且最终没有使用整个容量,我是否在浪费内存?

  3. 如果需要,这个额外的内存(我没有使用)会被分配给其他东西吗?

编辑:假设我有

 string a= "something";
 a = "ab";
Run Code Online (Sandbox Code Playgroud)

现在我知道a不会超过两个字符.所以打电话reserve(2)让记忆不浪费是明智的吗?

c++

4
推荐指数
1
解决办法
261
查看次数

标签 统计

c++ ×4

argparse ×1

c++11 ×1

c++17 ×1

lambda ×1

python ×1

standards ×1

std ×1

stl ×1