我可以在 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) 众所周知,匿名联合是一个未命名的联合定义,它不会同时定义任何变量。匿名联合的成员被注入到封闭的范围内。但是在 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] …
我正在做一个个人项目,一个模拟器.假设有两个寄存器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放在那里作为第二个字节.
有任何想法吗?
我的问题围绕复制构造和重新分配的机制。
我有一堂课,收集字符串。将字符串添加到集合后,该字符串将被复制并存储在向量中。但是由于我还需要访问所有字符串的集合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++(以及一般编译语言)的新手,正在 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++17 - The Complete Guide 一书,在constexpr
lambda 的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运行时(例如,使用静态变量)。因此,您可以考虑声明:Run Code Online (Sandbox Code Playgroud)constexpr auto squared = [](auto val) constexpr { // example 3 return val …
我正在尝试为 ORB 功能实现 C++17 可移植且高效的汉明距离函数,希望在为 x86 和 ARM 编译时自动使用 SIMD。
std::bitset
std::bitset<N>
提供了按位运算和计数的标准方式,并且它也优于__builtin_popcount
. cv::Mat
然而,它是一种拥有数据的容器类型,并且不容易从由 计算的存储的 256 位向量转换而来cv::ORB::detectAndCompute
。
该线程要求转换cv::Mat
为std::bitset<256>
. 我认为memcpy
它的答案不正确,因为我没有std::bitset
在https://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
我尝试使用以下线程中的解决方案在具有固定大小的类中创建向量向量,但无济于事。使用 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) 让我们假设如下:
我在 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)
这会是线程/进程间安全的吗?
注意:
这对于 来说并不安全std::atomic<>
,因为它不“承诺”有关共享内存的任何内容。此外,从两个不同的过程构建/销毁根本不清楚。
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)
我的i
和s
变量应该仍然在范围内并且不是右值,所以我不确定是什么触发了错误。如果我删除并直接在调用中args
调用to ,一切都会按预期进行。我缺少什么?std::make_format_args()
std::vformat()
这是我编译上述代码的命令:clang++-17 --std=c++23 -stdlib=libc++ -fsanitize=address fmt.cpp
。