Skip to content

Commit 25d8323

Browse files
authored
Merge pull request #5163 from MicrosoftDocs/main
1/22/2024 AM Publish
2 parents 7f54f65 + eb10b57 commit 25d8323

12 files changed

+161
-91
lines changed

docs/c-runtime-library/reference/vsnprintf-vsnprintf-vsnprintf-l-vsnwprintf-vsnwprintf-l.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ See [Behavior summary](#behavior-summary) for details.
125125

126126
Each of these functions takes a pointer to an argument list, then formats the data, and writes up to *`count`* characters to the memory pointed to by *`buffer`*. The **`vsnprintf`** function always writes a null terminator, even if it truncates the output. When you use **`_vsnprintf`** and **`_vsnwprintf`**, the buffer is null-terminated only if there's room at the end (that is, if the number of characters to write is less than *`count`*).
127127

128-
Beginning with the UCRT in Visual Studio 2015 and Windows 10, **`vsnprintf`** is no longer identical to **`_vsnprintf`**. The **`vsnprintf`** function conforms to the C99 standard; **`_vnsprintf`** is kept for backward compatibility with older code. The difference is that if you run out of buffer, `vsnprintf` null-terminates the end of the buffer and returns the number of characters that would have been required, while `_vsnprintf` doesn't null-terminate the buffer and returns -1. Also, `_vsnprintf()` includes one more character in the output because it doesn't null-terminate the buffer.
128+
Beginning with the UCRT in Visual Studio 2015 and Windows 10, **`vsnprintf`** is no longer identical to **`_vsnprintf`**. The **`vsnprintf`** function conforms to the C99 standard; **`_vsnprintf`** is kept for backward compatibility with older code. The difference is that if you run out of buffer, `vsnprintf` null-terminates the end of the buffer and returns the number of characters that would have been required, while `_vsnprintf` doesn't null-terminate the buffer and returns -1. Also, `_vsnprintf()` includes one more character in the output because it doesn't null-terminate the buffer.
129129

130130
> [!IMPORTANT]
131131
> To prevent certain kinds of security risks, ensure that *`format`* isn't a user-defined string. For more information, see [Avoiding buffer overruns](/windows/win32/SecBP/avoiding-buffer-overruns).

docs/cpp/inline-functions-cpp.md

Lines changed: 69 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -20,35 +20,38 @@ A function defined in the body of a class declaration is implicitly an inline fu
2020
In the following class declaration, the `Account` constructor is an inline function because it is defined in the body of the class declaration. The member functions `GetBalance`, `Deposit`, and `Withdraw` are specified `inline` in their definitions. The `inline` keyword is optional in the function declarations in the class declaration.
2121

2222
```cpp
23-
// Inline_Member_Functions.cpp
23+
// account.h
2424
class Account
2525
{
2626
public:
27-
Account(double initial_balance) { balance = initial_balance; }
28-
double GetBalance();
29-
double Deposit( double Amount );
30-
double Withdraw( double Amount );
27+
Account(double initial_balance)
28+
{
29+
balance = initial_balance;
30+
}
31+
32+
double GetBalance() const;
33+
double Deposit(double amount);
34+
double Withdraw(double amount);
35+
3136
private:
3237
double balance;
3338
};
3439

35-
inline double Account::GetBalance()
40+
inline double Account::GetBalance() const
3641
{
3742
return balance;
3843
}
3944

40-
inline double Account::Deposit( double Amount )
41-
{
42-
return ( balance += Amount );
43-
}
44-
45-
inline double Account::Withdraw( double Amount )
45+
inline double Account::Deposit(double amount)
4646
{
47-
return ( balance -= Amount );
47+
balance += amount;
48+
return balance;
4849
}
4950

50-
int main()
51+
inline double Account::Withdraw(double amount)
5152
{
53+
balance -= amount;
54+
return balance;
5255
}
5356
```
5457
@@ -90,10 +93,9 @@ Use the [`/Ob`](../build/reference/ob-inline-function-expansion.md) compiler opt
9093
```cpp
9194
// inline_keyword1.cpp
9295
// compile with: /c
93-
inline int max( int a , int b ) {
94-
if( a > b )
95-
return a;
96-
return b;
96+
inline int max(int a, int b)
97+
{
98+
return a < b ? b : a;
9799
}
98100
```
99101

@@ -105,13 +107,14 @@ A class's member functions can be declared inline, either by using the **`inline
105107
// inline_keyword2.cpp
106108
// compile with: /EHsc /c
107109
#include <iostream>
108-
using namespace std;
109110

110-
class MyClass {
111+
class MyClass
112+
{
111113
public:
112-
void print() { cout << i << ' '; } // Implicitly inline
114+
void print() { std::cout << i; } // Implicitly inline
115+
113116
private:
114-
int i;
117+
int i;
115118
};
116119
```
117120

@@ -152,13 +155,15 @@ A `Point` class can be defined as follows:
152155

153156
```cpp
154157
// when_to_use_inline_functions.cpp
158+
// compile with: /c
155159
class Point
156160
{
157161
public:
158-
// Define "accessor" functions as
159-
// reference types.
162+
// Define "accessor" functions
163+
// as reference types.
160164
unsigned& x();
161165
unsigned& y();
166+
162167
private:
163168
unsigned _x;
164169
unsigned _y;
@@ -168,13 +173,11 @@ inline unsigned& Point::x()
168173
{
169174
return _x;
170175
}
176+
171177
inline unsigned& Point::y()
172178
{
173179
return _y;
174180
}
175-
int main()
176-
{
177-
}
178181
```
179182

180183
Assuming coordinate manipulation is a relatively common operation in a client of such a class, specifying the two accessor functions (`x` and `y` in the preceding example) as **`inline`** typically saves the overhead on:
@@ -193,7 +196,9 @@ A macro has some things in common with an `inline` function. But there are impor
193196
```cpp
194197
#include <iostream>
195198

196-
#define mult(a, b) a * b
199+
#define mult1(a, b) a * b
200+
#define mult2(a, b) (a) * (b)
201+
#define mult3(a, b) ((a) * (b))
197202

198203
inline int multiply(int a, int b)
199204
{
@@ -202,40 +207,67 @@ inline int multiply(int a, int b)
202207

203208
int main()
204209
{
205-
std::cout << mult(5 + 5, 5 + 5) << std::endl; // outputs 35
206-
std::cout << multiply(5 + 5, 5 + 5) << std::endl; // outputs 100
210+
std::cout << (48 / mult1(2 + 2, 3 + 3)) << std::endl; // outputs 33
211+
std::cout << (48 / mult2(2 + 2, 3 + 3)) << std::endl; // outputs 72
212+
std::cout << (48 / mult3(2 + 2, 3 + 3)) << std::endl; // outputs 2
213+
std::cout << (48 / multiply(2 + 2, 3 + 3)) << std::endl; // outputs 2
207214

208-
std::cout << mult(2, 2.2) << std::endl>>; // no warning
215+
std::cout << mult3(2, 2.2) << std::endl; // no warning
209216
std::cout << multiply(2, 2.2); // Warning C4244 'argument': conversion from 'double' to 'int', possible loss of data
210217
}
211218
```
212219
213220
```Output
214-
35
215-
100
221+
33
222+
72
223+
2
224+
2
216225
4.4
217226
4
218227
```
219228

220229
Here are some of the differences between the macro and the inline function:
221230

222231
- Macros are always expanded inline. However, an inline function is only inlined when the compiler determines it is the optimal thing to do.
223-
- The macro may result in unexpected behavior. For example, the macro `mult(5+5,5+5)` expands to `5 + 5 * 5 + 5` resulting in 35, whereas the function evaluates `10 * 10`. You could address that by defining the macro as #define `mult(a, b) ((a)*(b))`.
232+
- The macro may result in unexpected behavior, which can lead to subtle bugs. For example, the expression `mult1(2 + 2, 3 + 3)` expands to `2 + 2 * 3 + 3` which evaluates to 11, but the expected result is 24. A seemingly valid fix is to add parentheses around both arguments of the function macro, resulting in `#define mult2(a, b) (a) * (b)`, which will solve the issue at hand but can still cause surprising behavior when part of a larger expression. That was demonstrated in the preceding example, and the problem could be addressed by defining the macro as such `#define mult3(a, b) ((a) * (b))`.
224233
- An inline function is subject to semantic processing by the compiler, whereas the preprocessor expands macros without that same benefit. Macros aren't type-safe, whereas functions are.
225234
- Expressions passed as arguments to inline functions are evaluated once. In some cases, expressions passed as arguments to macros can be evaluated more than once. For example, consider the following:
226235

227236
```cpp
237+
#include <iostream>
238+
228239
#define sqr(a) ((a) * (a))
229240

241+
int increment(int& number)
242+
{
243+
return number++;
244+
}
245+
246+
inline int square(int a)
247+
{
248+
return a * a;
249+
}
250+
230251
int main()
231252
{
232253
int c = 5;
233-
std::cout << sqr(c++) << std::endl; // outputs 25
234-
std::cout << c << std::endl; // outputs 7!
254+
std::cout << sqr(increment(c)) << std::endl; // outputs 30
255+
std::cout << c << std::endl; // outputs 7
256+
257+
c = 5;
258+
std::cout << square(increment(c)) << std::endl; // outputs 25
259+
std::cout << c; // outputs 6
235260
}
236261
```
237262
238-
In this example, the expression `c++` is evaluated twice; once for each occurrence of `a` in the macro expansion. Instead, if `sqr` were an inline function, the expression `c++` would be evaluated only once.
263+
```Output
264+
30
265+
7
266+
25
267+
6
268+
```
269+
270+
In this example, the function `increment` is called twice as the expression `sqr(increment(c))` expands to `((increment(c)) * (increment(c)))`. This caused the second invocation of `increment` to return 6, hence the expression evaluates to 30. Any expression that contains side effects may affect the result when used in a macro, examine the fully expanded macro to check if the behavior is intended. Instead, if the inline function `square` was used, the function `increment` would only be called once and the correct result of 25 will be obtained.
239271

240272
## See also
241273

docs/cpp/welcome-back-to-cpp-modern-cpp.md

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ title: "Welcome back to C++ - Modern C++"
33
description: "Describes the new programming idioms in Modern C++ and their rationale."
44
ms.date: 06/02/2022
55
ms.topic: "conceptual"
6-
ms.assetid: 1cb1b849-ed9c-4721-a972-fd8f3dab42e2
76
---
87
# Welcome back to C++ - Modern C++
98

@@ -64,10 +63,7 @@ apple_color["Granny Smith"] = "Green";
6463

6564
When performance optimization is needed, consider using:
6665

67-
- The [`array`](../standard-library/array-class-stl.md) type when embedding is important, for example, as a class member.
68-
6966
- Unordered associative containers such as [`unordered_map`](../standard-library/unordered-map-class.md). These have lower per-element overhead and constant-time lookup, but they can be harder to use correctly and efficiently.
70-
7167
- Sorted `vector`. For more information, see [Algorithms](../standard-library/algorithms.md).
7268

7369
Don't use C-style arrays. For older APIs that need direct access to the data, use accessor methods such as `f(vec.data(), vec.size());` instead. For more information about containers, see [C++ Standard Library Containers](../standard-library/stl-containers.md).
@@ -79,11 +75,8 @@ Before you assume that you need to write a custom algorithm for your program, fi
7975
Here are some important examples:
8076

8177
- `for_each`, the default traversal algorithm (along with range-based `for` loops).
82-
8378
- `transform`, for not-in-place modification of container elements
84-
8579
- `find_if`, the default search algorithm.
86-
8780
- `sort`, `lower_bound`, and the other default sorting and searching algorithms.
8881

8982
To write a comparator, use strict **`<`** and use *named lambdas* when you can.
Lines changed: 34 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,63 @@
11
---
22
description: "Learn more about: Compiler Error C2385"
33
title: "Compiler Error C2385"
4-
ms.date: "11/04/2016"
4+
ms.date: "1/19/2024"
55
f1_keywords: ["C2385"]
66
helpviewer_keywords: ["C2385"]
7-
ms.assetid: 6d3dd1f2-e56d-49d7-865c-6a9acdb17417
87
---
98
# Compiler Error C2385
109

11-
ambiguous access of 'member'
10+
> ambiguous access of 'member'
1211
13-
The member can derive from more than one object (it is inherited from more than one object). To resolve this error,
12+
A member is inherited from more than one base type, making unqualified access to that member ambiguous. To resolve this error:
1413

15-
- Make the member unambiguous by providing a cast.
16-
17-
- Rename the ambiguous members in the base classes.
14+
- Explicitly qualify access to the member.
15+
- Cast the object to the base class containing the member before accessing the member.
16+
- Rename the ambiguous member in the base class.
17+
- Bring the member into scope.
1818

1919
## Example
2020

21-
The following sample generates C2385.
21+
The following sample generates C2385:
2222

2323
```cpp
2424
// C2385.cpp
25-
// C2385 expected
26-
#include <stdio.h>
27-
2825
struct A
2926
{
30-
void x(int i)
31-
{
32-
printf_s("\nIn A::x");
33-
}
27+
void func1(int i) {}
28+
void func2() {}
3429
};
3530

3631
struct B
3732
{
38-
void x(char c)
39-
{
40-
printf_s("\nIn B::x");
41-
}
33+
void func1(char c) {}
34+
void func2() {}
4235
};
4336

44-
// Delete the following line to resolve.
45-
struct C : A, B {}
46-
47-
// Uncomment the following 4 lines to resolve.
48-
// struct C : A, B
49-
// {
50-
// using B::x;
51-
// using A::x;
52-
// };
37+
struct C : A, B
38+
{
39+
// Uncomment the following lines to resolve the first 2 errors
40+
// The error below for the call to c.func2() will remain
41+
// using A::func1;
42+
// using B::func1;
43+
};
5344

5445
int main()
5546
{
56-
C aC;
57-
aC.x(100);
58-
aC.x('c');
59-
}
47+
C c;
6048

61-
struct C : A, B
62-
{
63-
using B::x;
64-
using A::x;
65-
};
49+
c.func1(123); // C2385
50+
c.func1('a'); // C2385
51+
c.func2(); // C2385
52+
53+
c.A::func2(); // OK because explicitly qualified
54+
c.B::func2(); // OK because explicitly qualified
55+
static_cast<A>(c).func2(); // OK because of the cast
56+
static_cast<B>(c).func2(); // OK because of the cast
57+
}
6658
```
59+
60+
You can resolve the ambiguous calls to `func1` by bringing both overloads into scope. However, this doesn't work for `func2` because `A::func2` and `B::func2` don't take arguments, so calling them can't be differentiated by their parameters. You can resolve the issue by:
61+
- Introduce the one you want to use into scope
62+
- Explicitly qualify the call with the base type
63+
- Cast the object before calling the function.

docs/error-messages/compiler-warnings/c4834.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
description: "Learn about the cause and fixes for Compiler warning (level 1) C4834."
33
title: "Compiler warning (Level 1) C4834"
4-
ms.date: 07/26/2021
4+
ms.date: 01/18/2024
55
f1_keywords: ["C4834"]
66
helpviewer_keywords: ["C4834"]
77
---
@@ -11,7 +11,7 @@ helpviewer_keywords: ["C4834"]
1111
1212
## Remarks
1313

14-
Starting in the C++17 Standard, the `[[nodiscard]]` attribute specifies that a function's return value isn't intended to be discarded. If a caller discards the return value, the compiler generates warning C4834.
14+
Starting in the C++17 Standard, the `[[nodiscard]]` attribute specifies that a function's return value isn't intended to be discarded. If a caller discards the return value, the compiler generates warning C4834. Although this attribute was introduced in C++17, the compiler respects this attribute and generates warnings related to it when using `/std:c++14` and later.
1515

1616
To resolve this warning, consider why your code doesn't use the return value. Your use of the function may not match its intent. You can circumvent the warning by assigning the value to **`std::ignore`** or by casting it to **`void`** if discarding the value is intentional.
1717
Assignment to **`std::ignore`** is preferred over casting to **`void`** in C++11 and higher, as it makes your intent clearer and will not trigger [Warning C26457](../../code-quality/c26457.md) if enabled in your code analysis settings.

0 commit comments

Comments
 (0)