void foo(const auto& collection)
{
*collection.begin() = 104;
}
int main()
{
std::vector<int> ints {1, 2, 3, 4, 5};
foo(ints); // Error, as it should be
foo(ints | std::views::all); // Compiles and modifies the vector. Why?
return 0;
}
Run Code Online (Sandbox Code Playgroud)
如果函数的参数是类型,为什么左值引用的常量性会被完全忽略std::view?
编辑:
如果,正如您在注释中所写,const 视图引用与此上下文中的 const 指针类似,那么如果同一函数采用从右值对象构造的视图作为参数,为什么代码无法编译?
std::vector<int> getVec()
{
return std::vector{1, 2, 3, 4, 5};
}
void foo(const auto& collection)
{
*collection.begin() = 104; // Error: assignment of read-only location
}
int main()
{
foo(getVec() | std::views::all); // Nope! …Run Code Online (Sandbox Code Playgroud) 我知道,标记一个函数noexcept可能有助于[在某些情况下]获得许多很棒的优化,例如移动语义。但是假设,我的代码中有一个函数执行非常关键的操作,如果该函数失败,则意味着发生了非常糟糕的事情以至于无法恢复,并且该程序应该立即终止。如果我故意标记这样一个函数,noexcept即使我承认有异常的可能性,只是为了在发生异常时杀死程序怎么办?
有些东西告诉我这不是它应该使用的用途,但它是 的有效用途吗noexcept?
class C
{
public:
C(C&&) = default; // (1)
C& operator=(C&&) = default; // (1)
C(C&&) noexcept = default; // (2)
C& operator=(C&&) noexcept = default; // (2)
}
Run Code Online (Sandbox Code Playgroud)
据我所知,如果移动构造函数/赋值运算符是由用户隐式生成或显式默认的(1),编译器将noexcept根据类的所有成员是否noexcept为移动操作提供保证来决定是否应该使用这些特殊成员函数。但是,如果我想使用默认移动特殊成员并强制它们不noexcept考虑移动操作的底层成员异常保证,该怎么办?(1)和声明之间的编译器有什么区别吗(2)?
我有一个与磁盘上存储的某些文件相关的对象。该对象的构造函数接受该文件作为参数,读取它并根据文件内容的设置创建一个实际对象。在运行时该文件有可能被用户修改。该对象有一个方法来检查文件自上次读取以来是否已被修改,如果是这样,则必须更新该对象。对象内部有足够的成员需要更新,因此无需手动更新每个成员,只需创建一个新对象并将其移动到现有对象中会更方便(更少的键入和更好的可读性)。*this但在方法执行期间进行更改实际上是否安全,如下例所示?
void Object::update()
{
if (this->isModified(file)) // Check if a file has been modified since the last read
{
try
{
Object newObject(file); // May throw
*this = std::move(newObject); // Is it safe?
}
catch (const std::exception& ex)
{
// Invalidate and rethrow exception
this->invalidate();
throw(ex);
}
}
// ...
}
Run Code Online (Sandbox Code Playgroud) std::string str1{"This is a test string"};
std::string str2{std::move(str1)};
str1 = "This is a new content of this string";
// Use str1...
Run Code Online (Sandbox Code Playgroud)
我是否正确地认为str1现在处于有效状态并且在为其分配新值后可以完全安全地使用?
#include <iostream>
#include <vector>
#include <ranges>
int main()
{
std::vector<int> ints {1, 2, 3, 4, 5};
auto isEven = [] (const auto& element)
{
return element % 2 == 0;
};
auto even = ints | std::views::filter(isEven);
for (auto& element : even)
{
++element;
}
for (const auto& element : ints)
{
std::cout << element << "\n";
}
std::cout << "\n\n";
// Interesting things start further...
for (auto& element : even)
{
++element;
}
for (const auto& element : ints) …Run Code Online (Sandbox Code Playgroud) 我想我的问题很愚蠢,但尽管如此:
在我的 C++ 代码中,我使用一些遗留的 C 库(XLib)。为了使用这个库,必须首先打开到 X 服务器的连接:
::Display* const display = ::XOpenDisplay(nullptr);
Run Code Online (Sandbox Code Playgroud)
这种display结构广泛用于绝大多数 XLib 函数,包括分配和释放内存和系统资源(如字体、颜色图等)的函数。在我的代码中,我使用对象的构造函数和析构函数通过调用这些函数来分配和释放资源功能。问题是这样的:
int main()
{
::Display* const display = ::XOpenDisplay(nullptr);
// ...
Object1 object1(display, ...); // uses display inside the destructor
Object2 object2(display, ...); // uses display inside the destructor
Object3 object3(display, ...); // uses display inside the destructor
// ...
::XCloseDisplay(display); // invalidates the display structure
return 0;
}
Run Code Online (Sandbox Code Playgroud)
此示例会导致分段错误,因为在调用任何使用该结构的析构函数之前该display结构已失效。XCloseDisplay()为了避免这个问题,我可以将之前的所有代码放在XCloseDisplay()大括号中以限制对象的范围,但这会使代码向右移动,这看起来非常难看。
有什么办法可以XCloseDisplay()在之后打电话main()吗?