我有一堂课:
class Symbol_t {
public:
Symbol_t( const char* rawName ) {
memcpy( m_V, rawName, 6 * sizeof( char ) );
};
string_view strVw() const {
return string_view( m_V, 6 );
};
private:
char m_V[6];
}; // class Symbol_t
Run Code Online (Sandbox Code Playgroud)
并且有一个我无法修改的 lib-func:
extern bool loadData( const string& strSymbol );
Run Code Online (Sandbox Code Playgroud)
如果有局部变量:
Symbol_t symbol( "123456" );
Run Code Online (Sandbox Code Playgroud)
当我需要调用loadData时,我不敢这样做:
loadData( string( symbol.strVw().begin(), symbol.strVw().end() ) );
Run Code Online (Sandbox Code Playgroud)
我必须这样做:
string_view svwSym = symbol.strVw();
loadData( string( svw.begin(), svw.end() ) );
Run Code Online (Sandbox Code Playgroud)
我的问题:第一种方法正确吗?还是我必须使用第二个?
因为我认为在方法 1 中,我传递给 std::string 的构造函数的迭代器是两个不同的 string_vew 对象,理论上结果是未定义的,即使我们几乎所有的 C++ 编译器都会得到预期的结果。 …
我有如下功能:
const char* get_message() {
return "This is a constant message, will NOT change forever!";
};
const char* get_message2() {
return "message2";
};
Run Code Online (Sandbox Code Playgroud)
我计划在我的应用程序的任何地方使用它们,即使在不同的线程中。
const char*
我想知道这些字符串的生命周期,即在函数之外使用这些字符串是否安全get_message
。
我猜想硬编码const char*
字符串将被编译到应用程序的代码段而不是数据段中,所以也许像上面那样使用它们是安全的?
我正在使用 CMake-3.13.4 和 KDevelop-5.2.1。
我有一个最顶层的 CMakeLists.txt,它定义了我的目标的版本号。看起来像:
set( PROJECT_VERSION_MAJOR 1 )
set( PROJECT_VERSION_MINOR 4 )
set( PROJECT_VERSION_PATCH 7 )
...
add_executable( mytarget main.cpp XXX.cpp ... )
target_link_libraries( mytarget "stdc++fs" ${CMAKE_THREAD_LIBS_INIT} ... )
install( TARGETS mytarget RUNTIME DESTINATION . )
Run Code Online (Sandbox Code Playgroud)
我希望 CMake 自动将版本字符串附加到目标的文件名中。所以我的代码如下:
install( TARGETS mytarget RUNTIME DESTINATION . RENAME "mytarget-${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}" )
Run Code Online (Sandbox Code Playgroud)
但这不起作用。
有没有办法用CMake来完成?我最终想要的文件名是“mytarget-1.4.7”。
在C/C++中,我们可以声明/定义一个类型的函数指针,然后声明/定义这个类型的一些变量。但我认为这是模棱两可的。
例如:
typedef void ( *pFunc )();
// typedef void ( aFunc )();
void theFunc() {
cout << "theFunc has been called successfully." << endl;
};
int main() {
pFunc pf0 = theFunc;
pFunc pf1 = &theFunc;
pf0();
( *pf0 )();
pf1();
( *pf1 )();
};
Run Code Online (Sandbox Code Playgroud)
理论上,只有pFunc pf1 = &theFunc;
和(*pf1)();
是合法的,但以上都可以通过编译。
在Pascal语法中,我们需要分别定义函数的vars或函数指针的vars,它们的含义是不同的,而且更加清晰(至少我是这么认为的)!
此外,我们不能声明/定义函数的变量而不是函数指针的变量!我尝试了以下并失败了。
typedef void ( aFunc )();
aFunc af0 = theFunc;
Run Code Online (Sandbox Code Playgroud)
如果使用其他类型,例如 int/double,则有非常严格的语法限制我们正确使用它们。(如果int*
与 不同int
,为什么*pf0
与 相同pf0
?!) …
我用 i7 CPU 替换了我笔记本电脑的 i5 CPU,以便它可以运行得更快。但是因为i7的功率更大,温度也比以前高,所以我的笔记本经常死机。所以,我用 cpupower 来指定 CPU 的 MAX 频率,它起作用了。现在,我的问题是“有没有办法在启动时将 CPU 频率指定为 linux 内核的 cmd_line 参数?”,这样我就可以确保系统稳定正确地启动。
顺便说一句,如果新的cpu最多在2.5GHz的频率下运行,一切都好,性能比旧的高一倍。所以我觉得换我的CPU是值得的。
多谢!
正如我们所知,当一个可移动的物体被分配给另一个相同类型的物体时,它将不会被深深地复制.通过这种方式,我们可以节省大量时间.但是今天,我发现了一种现象.请查看以下代码.
#include <string>
#include <iostream>
int main() {
std::string s1 = "s1";
std::string s2 = "s2";
std::cout << " s1[" << ( void* ) &s1[0] << "]:" + s1
<< ", s2[" << ( void* ) &s2[0] << "]:" + s2
<< std::endl;
s1.swap( s2 );
std::cout << " s1[" << ( void* ) &s1[0] << "]:" + s1
<< ", s2[" << ( void* ) &s2[0] << "]:" + s2
<< std::endl;
s2 = std::move(s1);
std::cout << " s1[" …
Run Code Online (Sandbox Code Playgroud) 为了让我的代码更符合C++风格而不是C风格,我想替换errno
为std::errno
,并替换include <errno.h>
为include <cerrno>
.
令我惊讶的是,这些都不是std::errno
!
众所周知,许多 C 事物都有 C++ 等价物。举例来说:
在 c-source.c 中,我们通常这样编码:
#include <string.h>
print( strerro(1) );
Run Code Online (Sandbox Code Playgroud)
在c++source.cpp中,我们可以这样做:
#include <cstring>
std::cout << std::strerro(1);
Run Code Online (Sandbox Code Playgroud)
为什么存在却不std::errno
存在std::strerro
?
众所周知,在 x86/x86_64 等多字节字计算机中,逐字复制/移动大量内存(每步 4 或 8 个字节)比逐字节复制/移动更有效。
我很好奇 strncpy/memcpy/memmove 会以哪种方式做事,以及它们如何处理内存字对齐。
char buf_A[8], buf_B[8];
// I often want to code as this
*(double*)buf_A = *(double*)buf_B;
//in stead of this
strcpy(buf_A, buf_B);
// but it worsen the readability of my codes.
Run Code Online (Sandbox Code Playgroud) 我有一个类,它的负载非常重,因此创建/复制/移动此类的实例非常昂贵。由于应用程序完成初始化后它们不会改变,因此无需创建此类的临时对象。我只需要在容器(std::map
)中缓存对象,并在需要时提供“常量引用”。
必须强调的一点是,我正在寻找一种解决方案,可以在将对象添加到容器之前避免双重创建或不必要的复制(我不认为像 @getsoubl 提出的解决方案可以解决问题,因为它不会消除双重创建或不必要的复制)。
因此,我想将构造函数方法安排到类主体的“私有/受保护”部分,以禁止在“工厂方法”之外进行任何创建/复制/移动。以下是我的原始解决方案:
class MyClass {
public:
// methods of the class
static const MyClass & findObject( int iKey ) {
auto pair = mapObjects.try_emplace( iKey, iKey );
if ( pair.second )
cout << "New object has been created" << endl;
return pair.first->second;
};
// deleted
MyClass() = delete;
MyClass( MyClass & ) = delete;
MyClass( MyClass && ) = delete;
MyClass( const MyClass & ) = delete;
MyClass( const MyClass && ) = delete;
MyClass …
Run Code Online (Sandbox Code Playgroud) 有一个虚拟类作为回调接口,我既不能修改,也不能要求作者修复。类的唯一成员是很多可以覆盖的虚方法,以便让库回调到我的代码中。为了获得一些回调机会,我应该为那个虚拟类创建一个派生类,并覆盖相应的虚拟方法。如果我对某些回调机会不感兴趣,我只需要避免覆盖它们。
但是,该接口类的声明有一个缺陷——它的析构函数没有声明为 virtual。
例如:
class callback_t {
public:
virtual void onData( int ) {};
};
Run Code Online (Sandbox Code Playgroud)
我创建了一个子类并且不覆盖析构函数,但是当我删除类的动态对象时child_t
,我遇到来自编译器的警告(gcc9 with C++17):
删除具有非虚拟析构函数的多态类类型“child_t”的对象可能会导致未定义的行为。
class child_t : public callback_t {
public:
~child_t() {
// release things specific to the child...
};
void onData( int ) override {
// do things I want when onData
};
private:
int m_data = 0;
};
int main() {
child_t* pc = new child_t;
// pass pc into the routines of the library
// …
Run Code Online (Sandbox Code Playgroud) c++ polymorphism overriding derived-class virtual-destructor
我的开发/生产环境都是 CentOS-7.7。为了用 gcc-8.3.0 编译我的程序,我在我的开发环境中安装了“devtoolset-8”,但它不能像 CentOS7 最初附带的 gcc-4.8.5 一样使用。每次需要编译程序时,必须使用“scl enable devtoolset-8 -- bash”切换到gcc8而不是gcc4.8.5。
当程序部署到生产环境时,没有gcc8,也没有libstdc++.so.6.0.25,所以它不能运行。我猜 libstdc++.so.6.0.25 应该和 gcc8 一起发布?我既不能在生产环境上安装“devtoolset-8”,也不能在生产环境上从源代码构建 gcc8。CentOS官方yum repo安装的libstdc++版本是libstdc++.so.6.0.19,所以我的程序无法在production-env中加载。如何让这样的程序运行?
谢谢!请原谅我丑陋的英语。
我有一个非常大的结构,它具有自定义的复制构造函数、自定义的移动构造函数、自定义的移动分配器和自定义的复制分配器,但我还需要在某处使用指定初始化语法来初始化它,因为它非常大,而我只想仅初始化其中的几个字段,其余字段保留默认值。
\n例如:
\nstruct SA_t {\n int a;\n int b;\n int c;\n};\n\nint main() {\n SA_t sa1 { .a = 2, .b = 3, .c = 4,}; // no problem\n return EXIT_SUCCESS;\n};\n
Run Code Online (Sandbox Code Playgroud)\n但是当我为其添加自定义构造函数时,我根本无法使用指定初始化方法。
\nstruct SA_t {\n SA_t() {\n a = 0;\n b = 1;\n c = 2;\n };\n\n int a;\n int b;\n int c;\n};\n\nint main() {\n SA_t sa1 { .a = 2, .b = 3, .c = 4,}; /* no matching function for call to …
Run Code Online (Sandbox Code Playgroud) c++ constructor initialization default-constructor designated-initializer
我用 C++20 编写了一个无锁且线程安全的环形队列,到目前为止它可以工作。唯一不完美的是它必须有两个enque()
方法,一个接受对左值的 const 引用作为参数,另一个接受对右值的引用,以便将右值移入队列而不是再次构造。
之前版本的代码如下,只是一个骨架,进行简化:
\ntemplate <typename T>\nclass RingQue_t {\npublic:\n explicit RingQue_t( size_t capacity );\n ~RingQue_t();\n bool deque( T& dest_ ) { return true; };\n\n // If we offer a const ref, the compiler will select this one\n bool enque( const T& src_ ) {\n // a lot of same codes goes here for a same logic...\n\n new( _buff + _tail ) T( src_ );\n };\n\n // If we offer a rvalue ref, the compiler …
Run Code Online (Sandbox Code Playgroud) c++ copy-constructor rvalue-reference move-constructor perfect-forwarding
c++ ×9
string ×2
centos ×1
cmake ×1
constants ×1
constexpr ×1
constructor ×1
cpu ×1
devtoolset ×1
emplace ×1
errno ×1
factory ×1
frequency ×1
function ×1
gcc ×1
installation ×1
iterator ×1
kdevelop ×1
kernel ×1
lib ×1
libstdc++ ×1
lifetime ×1
linux ×1
memcpy ×1
memmove ×1
namespaces ×1
overriding ×1
pointers ×1
polymorphism ×1
reference ×1
std ×1
strcpy ×1
string-view ×1
strncpy ×1
typedef ×1
version ×1
yum ×1