小编Ted*_*gmo的帖子

在 C++98 中实现移动构造函数和移动赋值运算符以获得更好的性能

我可以在 C++98 中使用复制构造函数和赋值运算符模拟移动构造函数和移动赋值运算符的功能,以提高性能,只要我知道复制构造函数和复制赋值将只为代码中的临时对象调用,或者我在我的代码中插入针吗?眼睛?

我举了两个例子,一个是普通的复制构造函数和复制赋值运算符,另一个是模拟移动构造函数和移动赋值运算符,并在向量中推送 10000 个元素来调用复制构造函数。

普通复制构造函数和复制赋值运算符的示例(copy.cpp)

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

class MemoryBlock
{
public:

   // Simple constructor that initializes the resource.
   explicit MemoryBlock(int length)
      : _length(length)
      , _data(new int[length])
   {
   }

   // Destructor.
   ~MemoryBlock()
   {

      if (_data != NULL)
      {
         // Delete the resource.
         delete[] _data;
      }
   }


//copy constructor.
MemoryBlock(const MemoryBlock& other): _length(other._length)
      , _data(new int[other._length])
{

      std::copy(other._data, other._data + _length, _data);
}

// copy assignment operator.
MemoryBlock& operator=(MemoryBlock& other)
{
  //implementation of …
Run Code Online (Sandbox Code Playgroud)

c++ constructor vector copy-constructor c++98

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

在匿名联合成员的 lambda 表达式中捕获

众所周知,匿名联合是一个未命名的联合定义,它不会同时定义任何变量。匿名联合的成员被注入到封闭的范围内。但是在 lambda 表达式中捕获这些成员有什么限制吗?

在下面的示例程序中

int main() {
    union {
        int x{0};
        char y[4];
    };

    // error everywhere
    //[=]() { return x; };    
    //[&]() { return x; };

    // ok in GCC only
    [x]() { return x; };
    [&x]() { return x; };

    // ok in all
    [x=x]() { return x; };
    [&x=x]() { return x; };
}
Run Code Online (Sandbox Code Playgroud)

所有编译器都拒绝进行隐式捕获(通过值[=]和引用[&])。例如 Clang 的错误是

unnamed variable cannot be implicitly captured in a lambda expression
Run Code Online (Sandbox Code Playgroud)

至于显式捕获(通过值[x]和通过引用[&x] …

c++ lambda unions language-lawyer

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

有没有办法让两个不同大小的变量共享一个内存地址而不将它们声明为指针?

我正在做一个个人项目,一个模拟器.假设有两个寄存器H和L,每个寄存器长一个字节.所以我们可以用一个字节写入H或L. 但是,某些指令要求您将两个字节写入H和L或HL.第一个字节转到H,第二个转到L.根据矿山的实施方式,有些事情难以实施.

所以我的想法是让HL成为一个双字节的单词.然而,仍将存在H和L的变量,其共享相同的地址作为HL的第一字节和分别HL的第二字节.

我可以做指针,我真的不想将所有寄存器声明为指针.

我想的一件事就是工会,就像这样:

union {
    BYTE H;
    WORD HL;
}
Run Code Online (Sandbox Code Playgroud)

但后来我不知道如何把L放在那里作为第二个字节.

有任何想法吗?

c++ z80

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

存储指向std :: string数据的指针是否安全?

我的问题围绕复制构造和重新分配的机制。

我有一堂课,收集字符串。将字符串添加到集合后,该字符串将被复制并存储在向量中。但是由于我还需要访问所有字符串的集合const char * const*,因此我还通过来存储指向每个字符串数据的指针.c_str()

class MyStrings {
private:
    std::vector<std::string> names;
    std::vector<const char*> cStringPointers;
public:
    const char *const *Data() const
    {
        return this->cStringPointers.data();
    }

    void Add(const std::string &name)
    {
        // copy [name] and store the copy in [this->names].
        this->names.push_back(name); 
        // Store the pointer to the data of the copy.
        this->cStringPointers.push_back(this->names.back().c_str());
    }
}
Run Code Online (Sandbox Code Playgroud)

我知道,存储指向向量元素的指针是不好的,因为当向量被调整大小(即必须重新分配其内存)时,这些指针将不再有效。

但是我只存储指向数据的指针。所以这是我的想法:

如果names调整大小,它将移动构造它包含的所有字符串,因此这些字符串将不会分配新的内存,而是仅使用已分配的内存,因此我的指针cStringPointers仍然有效。

我的问题现在很简单:我是否错过了一些会使该代码不安全或导致未定义行为的东西?

(假设我不使用任何奇异的architexture和/或编译器。)

c++

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

由于在 Bjarne Stroustrup "Programming and Practices using c++" 中找不到符号导致的链接错误

我是 C++(以及一般编译语言)的新手,正在 Bjarne Stroustrup“使用 C++ 进行编程和实践”的第 8 章末尾进行练习,但是当我尝试编译代码时出现以下错误

?  Desktop g++ -std=c++11 *.cpp -o use
Undefined symbols for architecture x86_64:
  "_foo", referenced from:
      print_foo() in my-4f7853.o
      _main in use-46cb26.o
     (maybe you meant: __Z9print_foov)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Run Code Online (Sandbox Code Playgroud)

我也试过使用g++ -c my.cpp use.cpp后跟,g++ -o use.exe my.o use.o但这给出了同样的错误。我尝试的另一种方法是g++ -c use.cpp -o use.exe,但是use.exe在运行时没有产生任何输出。源代码文件是

我的.h

extern int foo;
void print_foo(); …
Run Code Online (Sandbox Code Playgroud)

c++ g++ clang linker-errors

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

constexpr 与 lambda 表达式的 C++ 用法

我正在阅读C++17 - The Complete Guide 一书,在constexprlambda 的6.1 节中,作者给出了两个例子:

auto squared1 = [](auto val) constexpr { // example 1. compile-time lambda calls
  return val * val;
};
Run Code Online (Sandbox Code Playgroud)

constexpr auto squared2 = [](auto val) { // example 2. compile-time initialization
  return val * val;
};
Run Code Online (Sandbox Code Playgroud)

并说这两个彼此不同,因为示例 1在编译时评估,示例 2在编译时初始化。


然后作者做了以下我不完全理解的陈述:

如果(仅)lambda 是constexpr它可以在编译时使用,但是如果由 lambda 初始化的(闭包)对象是constexpr,则该对象在程序启动时被初始化,但 lambda 可能仍然是一个只能在以下情况下使用的 lambda运行时(例如,使用静态变量)。因此,您可以考虑声明:

constexpr auto squared = [](auto val) constexpr { // example 3
  return val …
Run Code Online (Sandbox Code Playgroud)

c++ lambda constexpr c++17

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

是否有类似于 std::bitset 的非拥有引用来为其他容器中的数据提供按位操作和计数?

我正在尝试为 ORB 功能实现 C++17 可移植且高效的汉明距离函数,希望在为 x86 和 ARM 编译时自动使用 SIMD。

有问题std::bitset

std::bitset<N>提供了按位运算和计数的标准方式,并且它也优于__builtin_popcount. cv::Mat然而,它是一种拥有数据的容器类型,并且不容易从由 计算的存储的 256 位向量转换而来cv::ORB::detectAndCompute

该线程要求转换cv::Matstd::bitset<256>. 我认为memcpy它的答案不正确,因为我没有std::bitsethttps://en.cppreference.com/w/cpp/utility/bitset中找到内存布局。此外,std::bitset构造函数不支持初始化超过位sizeof(unsigned long long)

我的实施有问题

为了避免复制,我当前的实现使用类似 span 的类:

struct ORB_view {
  inline static constexpr int length = 256 / sizeof(uint32_t) / 8;
  const uint32_t* data;
};
Run Code Online (Sandbox Code Playgroud)

但是,这不能直接使用按位运算和 popcount,并且会导致在实现中出现显式的 SIMD 指令,我希望通过使用std::bitset<N>::count().

我的期望是什么

因此,在这种情况下,提供按位运算和计数的非拥有引用将非常有帮助。所需的功能是:

  • 没有数据副本,
  • 固定长度为std::bitset
  • 按位异或运算和 popcount
  • 没有针对 ARM …

c++ simd bitwise-operators std-bitset c++17

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

在 C++17 中初始化整数向量的向量

我尝试使用以下线程中的解决方案在具有固定大小的类中创建向量向量,但无济于事。使用 boost 分配初始化具有固定大小的向量的向量

由于它已有 7 年历史,我认为这可能与 C++17 的变化有关,但我不确定问题出在哪里。IDE 告诉我的错误是第一个参数上的“预期类型说明符”。查看构造函数的文档,似乎没有什么问题,除非我错过了一些东西。

class SudokuSolver {

public:
    SudokuSolver() {}

    ~SudokuSolver() {}

private:
    std::vector<std::vector<int>> sudoku_field(9, std::vector<int>(9, 0));
};
Run Code Online (Sandbox Code Playgroud)

c++ stdvector c++17

3
推荐指数
1
解决办法
91
查看次数

在共享内存上使用 volatile 安全吗?

让我们假设如下:

我在 Linux / Mac OS 上有两个进程。

我有mmap共享内存(或在文件中)。

然后在这两个过程中我都有以下内容:

struct Data{
   volatile int reload = 0; // using int because is more standard
   // more things in the future...
};
void *mmap_memory = mmap(...);
Data *data = static_cast<Data *>(mmap_memory); // suppose size is sufficient and all OK
Run Code Online (Sandbox Code Playgroud)

然后在我做的其中一个过程中:

//...
data->reload = 1;
//...
Run Code Online (Sandbox Code Playgroud)

在另一个我做的:

while(...){
    do_some_work();
    //...
    if (data->reload == 1)
        do_reload();
}
Run Code Online (Sandbox Code Playgroud)

这会是线程/进程间安全的吗?

想法来自这里:
https://embeddedartistry.com/blog/2019/03/11/improve-volatile-usage-with-volatile_load-and-volatile_store/

注意:
这对于 来说并不安全std::atomic<>,因为它不“承诺”有关共享内存的任何内容。此外,从两个不同的过程构建/销毁根本不清楚。

c++ volatile shared-memory stdatomic

3
推荐指数
1
解决办法
348
查看次数

使用 std::format_args 解决范围后堆栈使用问题

std::format_args当我尝试与 一起使用时,出现 stack-use-after-scope 错误std::vformat()。重现它的简单代码是:

#include <format>
#include <iostream>
#include <string>

int main() {
    int i = 42;
    std::string s = "hello";
    std::format_args args = std::make_format_args(i, s);
    std::cout << std::vformat("Number: {}, Word: {}", args) << '\n';

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我的is变量应该仍然在范围内并且不是右值,所以我不确定是什么触发了错误。如果我删除并直接在调用中args调用to ,一切都会按预期进行。我缺少什么?std::make_format_args()std::vformat()

这是我编译上述代码的命令:clang++-17 --std=c++23 -stdlib=libc++ -fsanitize=address fmt.cpp

c++ address-sanitizer c++20 stdformat

3
推荐指数
1
解决办法
84
查看次数